Merge branch 'master' of https://github.com/jclouds/jclouds into 1.5.x

* 'master' of https://github.com/jclouds/jclouds: (25 commits)
  Moved HP Storage Container Metadata parsing to Swift since it's a standard Swift feature. Moved HP Storage createContainer(String, CreateContainerOptions) to CommonSwiftClient since it's a standard Swift feature. Added support for setting Swift Container Metadata. Added support for deleting Swift Container Metadata. Added copy object feature to Swift. Removed unnecessary TODO comment. Changed DeleteContainerMetadataOptions to just be a List. Changed CopyObjectOptions to be just be a String. Changed CommonSwiftClient.setContainerMetadata() to use just a Map for metadata. Added ExpectTests. Changed setContainerMetadata() to use Iterable instead of List for more generic type goodness. Changed copyObject() to use 4 String params instead of 2 String params to be similar to other such methods in jclouds.
  issue 830: added systemadmin package; more tests fixed
  CDMI: adding support for 1) query parameters 2) non-cdmi content data object operations
  Javadoc update for CloudStack Template.getStatus()
  CloudStack template status parsing update
  merge
  azure management base implementation
  Update parsing of Status in CloudStack Template
  default region endpoint for rackspace legacy apis
  issue 830: fixed VAppTemplateApiLiveTest.deleteVAppTemplate
  Issue 1075:switch to use jetty for java install/web service tests
  nslookup on CentOS 6.2 doesn't set error code when failing, so grep expected output instead
  review addressed
  issue 830: keypair
  Added test descriptions and dependencies to basic Nova live tests
  Configure duplicates plugin to ignore .gitattributes
  decrufted metadataapi
  configure .gitattributes to not convert shell scripts to CRLF on Windows
  Correct typo
  issue 830: more LiveTests fixed on query, vapp, vapptemplate and vdc features
  ...
diff --git a/apis/cloudfiles/src/main/java/org/jclouds/cloudfiles/config/CloudFilesRestClientModule.java b/apis/cloudfiles/src/main/java/org/jclouds/cloudfiles/config/CloudFilesRestClientModule.java
index bfcbd32..f927e9e 100644
--- a/apis/cloudfiles/src/main/java/org/jclouds/cloudfiles/config/CloudFilesRestClientModule.java
+++ b/apis/cloudfiles/src/main/java/org/jclouds/cloudfiles/config/CloudFilesRestClientModule.java
@@ -18,7 +18,7 @@
  */
 package org.jclouds.cloudfiles.config;
 
-import static org.jclouds.util.Suppliers2.getLastValueInMap;
+import static org.jclouds.util.Suppliers2.valueForKey;
 
 import java.net.URI;
 
@@ -29,12 +29,12 @@
 import org.jclouds.cloudfiles.CloudFilesClient;
 import org.jclouds.location.suppliers.RegionIdToURISupplier;
 import org.jclouds.openstack.keystone.v1_1.config.AuthenticationServiceModule;
+import org.jclouds.openstack.keystone.v1_1.suppliers.V1DefaultRegionIdSupplier;
 import org.jclouds.openstack.swift.CommonSwiftAsyncClient;
 import org.jclouds.openstack.swift.CommonSwiftClient;
 import org.jclouds.openstack.swift.Storage;
 import org.jclouds.openstack.swift.config.SwiftRestClientModule;
 import org.jclouds.rest.ConfiguresRestClient;
-import org.jclouds.rest.annotations.ApiVersion;
 
 import com.google.common.base.Supplier;
 import com.google.common.collect.ImmutableMap;
@@ -62,15 +62,19 @@
       @Provides
       @Singleton
       @CDNManagement
-      protected Supplier<URI> provideCDNUrl(RegionIdToURISupplier.Factory factory, @ApiVersion String apiVersion) {
-         return getLastValueInMap(factory.createForApiTypeAndVersion("cloudFilesCDN", apiVersion));
+      protected Supplier<URI> provideCDNUrl(RegionIdToURISupplier.Factory factory,
+               V1DefaultRegionIdSupplier.Factory defaultRegion) {
+         return valueForKey(factory.createForApiTypeAndVersion("cloudFilesCDN", null),
+                  defaultRegion.createForApiType("cloudFilesCDN"));
       }
 
       @Provides
       @Singleton
       @Storage
-      protected Supplier<URI> provideStorageUrl(RegionIdToURISupplier.Factory factory, @ApiVersion String apiVersion) {
-         return getLastValueInMap(factory.createForApiTypeAndVersion("cloudFiles", apiVersion));
+      protected Supplier<URI> provideStorageUrl(RegionIdToURISupplier.Factory factory,
+               V1DefaultRegionIdSupplier.Factory defaultRegion) {
+         return valueForKey(factory.createForApiTypeAndVersion("cloudFiles", null),
+                  defaultRegion.createForApiType("cloudFiles"));
       }
    }
 
diff --git a/apis/cloudfiles/src/test/java/org/jclouds/cloudfiles/CloudFilesClientExpectTest.java b/apis/cloudfiles/src/test/java/org/jclouds/cloudfiles/CloudFilesClientExpectTest.java
new file mode 100644
index 0000000..f69f2c2
--- /dev/null
+++ b/apis/cloudfiles/src/test/java/org/jclouds/cloudfiles/CloudFilesClientExpectTest.java
@@ -0,0 +1,56 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.cloudfiles;
+
+import org.jclouds.cloudfiles.internal.BaseCloudFilesRestClientExpectTest;
+import org.jclouds.http.HttpRequest;
+import org.jclouds.http.HttpResponse;
+import org.testng.annotations.Test;
+
+/**
+ * 
+ * @author Adrian Cole
+ */
+@Test(groups = "unit", testName = "CloudFilesClientExpectTest")
+public class CloudFilesClientExpectTest extends BaseCloudFilesRestClientExpectTest {
+
+   public void deleteContainerReturnsTrueOn200And404() {
+
+      HttpRequest deleteContainer = HttpRequest
+               .builder()
+               .method("DELETE")
+               .endpoint(
+                        "https://storage101.lon3.clouddrive.com/v1/MossoCloudFS_83a9d536-2e25-4166-bd3b-a503a934f953/container")
+               .addHeader("X-Auth-Token", authToken).build();
+
+      HttpResponse containerDeleted = HttpResponse.builder().statusCode(204).message("HTTP/1.1 204 No Content").build();
+
+      CloudFilesClient clientWhenContainerExists = requestsSendResponses(initialAuth, responseWithAuth, deleteContainer,
+               containerDeleted);
+      assert clientWhenContainerExists.deleteContainerIfEmpty("container");
+
+      HttpResponse containerNotFound = HttpResponse.builder().statusCode(404).message("HTTP/1.1 404 Not Found").build();
+
+      CloudFilesClient clientWhenContainerDoesntExist = requestsSendResponses(initialAuth, responseWithAuth, deleteContainer,
+               containerNotFound);
+      assert clientWhenContainerDoesntExist.deleteContainerIfEmpty("container");
+
+   }
+
+}
\ No newline at end of file
diff --git a/apis/cloudfiles/src/test/java/org/jclouds/cloudfiles/CloudFilesClientLiveTest.java b/apis/cloudfiles/src/test/java/org/jclouds/cloudfiles/CloudFilesClientLiveTest.java
index 7d4a228..b39533b 100644
--- a/apis/cloudfiles/src/test/java/org/jclouds/cloudfiles/CloudFilesClientLiveTest.java
+++ b/apis/cloudfiles/src/test/java/org/jclouds/cloudfiles/CloudFilesClientLiveTest.java
@@ -96,6 +96,7 @@
          Set<ContainerCDNMetadata> cdnMetadataList = getApi().listCDNContainers();
          assertTrue(cdnMetadataList.size() >= 1);
 
+         cdnMetadata = getApi().getCDNMetadata(containerNameWithCDN);
          final long initialTTL = cdnMetadata.getTTL();
          assertTrue(cdnMetadataList.contains(new ContainerCDNMetadata(containerNameWithCDN, true, initialTTL, cdnUri)));
 
diff --git a/apis/cloudfiles/src/test/java/org/jclouds/cloudfiles/internal/BaseCloudFilesRestClientExpectTest.java b/apis/cloudfiles/src/test/java/org/jclouds/cloudfiles/internal/BaseCloudFilesRestClientExpectTest.java
new file mode 100644
index 0000000..144d2c1
--- /dev/null
+++ b/apis/cloudfiles/src/test/java/org/jclouds/cloudfiles/internal/BaseCloudFilesRestClientExpectTest.java
@@ -0,0 +1,51 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.cloudfiles.internal;
+
+import java.util.Properties;
+
+import org.jclouds.apis.ApiMetadata;
+import org.jclouds.cloudfiles.CloudFilesApiMetadata;
+import org.jclouds.cloudfiles.CloudFilesClient;
+import org.jclouds.openstack.keystone.v1_1.internal.BaseKeystoneRestClientExpectTest;
+
+/**
+ * Base class for writing CloudFiles Rest Client Expect tests
+ * 
+ * @author Adrian Cole
+ */
+public class BaseCloudFilesRestClientExpectTest extends BaseKeystoneRestClientExpectTest<CloudFilesClient> {
+
+   public BaseCloudFilesRestClientExpectTest() {
+      provider = "cloudfiles";
+   }
+
+   @Override
+   protected Properties setupProperties() {
+      Properties overrides = new Properties();
+      overrides.setProperty(provider + ".endpoint", endpoint);
+      return overrides;
+   }
+
+   @Override
+   protected ApiMetadata createApiMetadata() {
+      return new CloudFilesApiMetadata();
+   }
+
+}
diff --git a/apis/cloudservers/src/test/java/org/jclouds/cloudservers/internal/BaseCloudServersRestClientExpectTest.java b/apis/cloudservers/src/test/java/org/jclouds/cloudservers/internal/BaseCloudServersRestClientExpectTest.java
index f6018a9..cc66f0f 100644
--- a/apis/cloudservers/src/test/java/org/jclouds/cloudservers/internal/BaseCloudServersRestClientExpectTest.java
+++ b/apis/cloudservers/src/test/java/org/jclouds/cloudservers/internal/BaseCloudServersRestClientExpectTest.java
@@ -29,7 +29,6 @@
 import org.jclouds.cloudservers.config.CloudServersRestClientModule;
 import org.jclouds.date.internal.SimpleDateFormatDateService;
 import org.jclouds.openstack.filters.AddTimestampQuery;
-import org.jclouds.openstack.keystone.v1_1.config.AuthenticationServiceModule;
 import org.jclouds.openstack.keystone.v1_1.internal.BaseKeystoneRestClientExpectTest;
 import org.jclouds.rest.ConfiguresRestClient;
 
@@ -67,13 +66,6 @@
     * override so that we can control the timestamp used in
     * {@link AddTimestampQuery}
     */
-   public static class TestAuthenticationServiceModule extends AuthenticationServiceModule {
-      @Override
-      protected void configure() {
-         super.configure();
-      }
-   }
-
    @Override
    protected Module createModule() {
       return new TestCloudServersRestClientModule();
diff --git a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/domain/Template.java b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/domain/Template.java
index 0891c83..749a160 100644
--- a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/domain/Template.java
+++ b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/domain/Template.java
@@ -23,6 +23,7 @@
 import java.beans.ConstructorProperties;
 import java.util.Date;
 
+import com.google.common.base.Strings;
 import org.jclouds.javax.annotation.Nullable;
 
 import com.google.common.base.Objects;
@@ -82,9 +83,14 @@
       UPLOAD_IN_PROGRESS, UNRECOGNIZED;
 
       public static Status fromValue(String state) {
-         if (state.equals("Download Complete")) {
-            return DOWNLOADED;
-         }
+         // Statuses are in free text form. These are the ones in CloudStack 3.0.4 source
+         // https://github.com/CloudStack/CloudStack/blob/e2e76c70ec51bfb35d755371f6c33856cef8a277/server/src/com/cloud/api/ApiResponseHelper.java#L1968
+         if (Strings.isNullOrEmpty(state)) { return UNKNOWN; }
+         else if (state.equals("Processing")) { return DOWNLOAD_IN_PROGRESS; }
+         else if (state.endsWith("% Downloaded")) { return DOWNLOAD_IN_PROGRESS; }
+         else if (state.equals("Installing Template")) { return DOWNLOAD_IN_PROGRESS; }
+         else if (state.equals("Installing ISO")) { return DOWNLOAD_IN_PROGRESS; }
+         else if (state.equals("Download Complete")) { return DOWNLOADED; }
          try {
             return valueOf(checkNotNull(state, "state"));
          } catch (IllegalArgumentException e) {
@@ -646,6 +652,14 @@
    }
 
    /**
+    * Retrieve the status of the template.
+    *
+    * <p>Note that in CloudStack 2.2.x through to at least 3.0.4, the possible status values are
+    * not well defined by CloudStack. CloudStack returns a plain-text English string for UI
+    * display, which jclouds attempts to parse into an enumeration, but the mapping is incomplete.
+    * This method should be reliable for the common cases, but it is possible (particularly for
+    * error statuses) that this method will return UNRECOGNIZED.</p>
+    *
     * @return status of the template
     */
    @Nullable
diff --git a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/NovaComputeService.java b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/NovaComputeService.java
index f62ef07..2114043 100644
--- a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/NovaComputeService.java
+++ b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/NovaComputeService.java
@@ -155,7 +155,7 @@
       Optional<? extends KeyPairApi> keyPairApi = novaApi.getKeyPairExtensionForZone(zoneId);
       if (keyPairApi.isPresent()) {
          for (String group : groups) {
-            for (Map<String, KeyPair> view : keyPairApi.get().listKeyPairs()) {
+            for (Map<String, ? extends KeyPair> view : keyPairApi.get().listKeyPairs()) {
                for (KeyPair pair : Iterables.filter(view.values(),
                         KeyPairPredicates.nameMatches(namingConvention.create().containsGroup(group)))) {
                   ZoneAndName zoneAndName = ZoneAndName.fromZoneAndName(zoneId, pair.getName());
diff --git a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/config/NovaComputeServiceContextModule.java b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/config/NovaComputeServiceContextModule.java
index 8bee10a..9b401d1 100644
--- a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/config/NovaComputeServiceContextModule.java
+++ b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/config/NovaComputeServiceContextModule.java
@@ -129,7 +129,7 @@
 
       bind(TemplateOptions.class).to(NovaTemplateOptions.class);
 
-      bind(new TypeLiteral<CacheLoader<ZoneAndId, Iterable<FloatingIP>>>() {
+      bind(new TypeLiteral<CacheLoader<ZoneAndId, Iterable<? extends FloatingIP>>>() {
       }).annotatedWith(Names.named("FLOATINGIP")).to(LoadFloatingIpsForInstance.class);
 
       bind(new TypeLiteral<Function<ZoneSecurityGroupNameAndPorts, SecurityGroupInZone>>() {
@@ -163,8 +163,8 @@
    @Provides
    @Singleton
    @Named("FLOATINGIP")
-   protected LoadingCache<ZoneAndId, Iterable<FloatingIP>> instanceToFloatingIps(
-            @Named("FLOATINGIP") CacheLoader<ZoneAndId, Iterable<FloatingIP>> in) {
+   protected LoadingCache<ZoneAndId, Iterable<? extends FloatingIP>> instanceToFloatingIps(
+            @Named("FLOATINGIP") CacheLoader<ZoneAndId, Iterable<? extends FloatingIP>> in) {
       return CacheBuilder.newBuilder().build(in);
    }
 
diff --git a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/functions/AllocateAndAddFloatingIpToNode.java b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/functions/AllocateAndAddFloatingIpToNode.java
index 6e2a59a..0e1193d 100644
--- a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/functions/AllocateAndAddFloatingIpToNode.java
+++ b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/functions/AllocateAndAddFloatingIpToNode.java
@@ -61,11 +61,11 @@
 
    private final Predicate<AtomicReference<NodeMetadata>> nodeRunning;
    private final NovaApi novaApi;
-   private final LoadingCache<ZoneAndId, Iterable<FloatingIP>> floatingIpCache;
+   private final LoadingCache<ZoneAndId, Iterable<? extends FloatingIP>> floatingIpCache;
 
    @Inject
    public AllocateAndAddFloatingIpToNode(@Named(TIMEOUT_NODE_RUNNING) Predicate<AtomicReference<NodeMetadata>> nodeRunning,
-            NovaApi novaApi, @Named("FLOATINGIP") LoadingCache<ZoneAndId, Iterable<FloatingIP>> floatingIpCache) {
+            NovaApi novaApi, @Named("FLOATINGIP") LoadingCache<ZoneAndId, Iterable<? extends FloatingIP>> floatingIpCache) {
       this.nodeRunning = checkNotNull(nodeRunning, "nodeRunning");
       this.novaApi = checkNotNull(novaApi, "novaApi");
       this.floatingIpCache = checkNotNull(floatingIpCache, "floatingIpCache");
diff --git a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/functions/RemoveFloatingIpFromNodeAndDeallocate.java b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/functions/RemoveFloatingIpFromNodeAndDeallocate.java
index df73e69..00f93cb 100644
--- a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/functions/RemoveFloatingIpFromNodeAndDeallocate.java
+++ b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/functions/RemoveFloatingIpFromNodeAndDeallocate.java
@@ -47,11 +47,11 @@
    protected Logger logger = Logger.NULL;
 
    private final NovaApi novaApi;
-   private final LoadingCache<ZoneAndId, Iterable<FloatingIP>> floatingIpCache;
+   private final LoadingCache<ZoneAndId, Iterable<? extends FloatingIP>> floatingIpCache;
 
    @Inject
    public RemoveFloatingIpFromNodeAndDeallocate(NovaApi novaApi,
-            @Named("FLOATINGIP") LoadingCache<ZoneAndId, Iterable<FloatingIP>> floatingIpCache) {
+            @Named("FLOATINGIP") LoadingCache<ZoneAndId, Iterable<? extends FloatingIP>> floatingIpCache) {
       this.novaApi = checkNotNull(novaApi, "novaApi");
       this.floatingIpCache = checkNotNull(floatingIpCache, "floatingIpCache");
    }
diff --git a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/loaders/LoadFloatingIpsForInstance.java b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/loaders/LoadFloatingIpsForInstance.java
index 578d0b1..d773bd5 100644
--- a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/loaders/LoadFloatingIpsForInstance.java
+++ b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/loaders/LoadFloatingIpsForInstance.java
@@ -40,7 +40,7 @@
  * @author Adam Lowe
  */
 @Singleton
-public class LoadFloatingIpsForInstance extends CacheLoader<ZoneAndId, Iterable<FloatingIP>> {
+public class LoadFloatingIpsForInstance extends CacheLoader<ZoneAndId, Iterable<? extends FloatingIP>> {
    private final NovaApi api;
 
    @Inject
@@ -49,7 +49,7 @@
    }
 
    @Override
-   public Iterable<FloatingIP> load(final ZoneAndId key) throws Exception {
+   public Iterable<? extends FloatingIP> load(final ZoneAndId key) throws Exception {
       String zone = key.getZone();
       Optional<? extends FloatingIPApi> ipApiOptional = api.getFloatingIPExtensionForZone(zone);
       if (ipApiOptional.isPresent()) {
diff --git a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/domain/KeyPair.java b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/domain/KeyPair.java
index cb59e67..f14332e 100644
--- a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/domain/KeyPair.java
+++ b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/domain/KeyPair.java
@@ -174,8 +174,13 @@
    }
    
    protected ToStringHelper string() {
-      return Objects.toStringHelper(this)
-            .add("publicKey", publicKey).add("privateKey", privateKey).add("userId", userId).add("name", name).add("fingerprint", fingerprint);
+      return Objects.toStringHelper("")
+            .omitNullValues()
+            .add("public_key", publicKey)
+            .add("private_key", privateKey)
+            .add("user_id", userId)
+            .add("name", name)
+            .add("fingerprint", fingerprint);
    }
    
    @Override
diff --git a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/extensions/FloatingIPApi.java b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/extensions/FloatingIPApi.java
index dcc0d76..45ee544 100644
--- a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/extensions/FloatingIPApi.java
+++ b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/extensions/FloatingIPApi.java
@@ -42,7 +42,7 @@
     * 
     * @return all Floating IPs
     */
-   Set<FloatingIP> listFloatingIPs();
+   Set<? extends FloatingIP> listFloatingIPs();
 
    /**
     * Get a specific Floating IP address
diff --git a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/extensions/FloatingIPAsyncApi.java b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/extensions/FloatingIPAsyncApi.java
index 2c09f82..d0db242 100644
--- a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/extensions/FloatingIPAsyncApi.java
+++ b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/extensions/FloatingIPAsyncApi.java
@@ -70,7 +70,7 @@
    @SelectJson("floating_ips")
    @Consumes(MediaType.APPLICATION_JSON)
    @ExceptionParser(ReturnEmptySetOnNotFoundOr404.class)
-   ListenableFuture<Set<FloatingIP>> listFloatingIPs();
+   ListenableFuture<? extends Set<? extends FloatingIP>> listFloatingIPs();
 
    /**
     * @see FloatingIPApi#getFloatingIP
@@ -80,7 +80,7 @@
    @SelectJson("floating_ip")
    @Consumes(MediaType.APPLICATION_JSON)
    @ExceptionParser(ReturnNullOnNotFoundOr404.class)
-   ListenableFuture<FloatingIP> getFloatingIP(@PathParam("id") String id);
+   ListenableFuture<? extends FloatingIP> getFloatingIP(@PathParam("id") String id);
 
    /**
     * @see FloatingIPApi#allocate
@@ -92,7 +92,7 @@
    @Produces(MediaType.APPLICATION_JSON)
    @ExceptionParser(ReturnNullOnNotFoundOr404.class)
    @Payload("{}")
-   ListenableFuture<FloatingIP> allocate();
+   ListenableFuture<? extends FloatingIP> allocate();
 
    /**
     * @see FloatingIPApi#deallocate
diff --git a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/extensions/HostAdministrationApi.java b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/extensions/HostAdministrationApi.java
index 8b305e3..5b1666f 100644
--- a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/extensions/HostAdministrationApi.java
+++ b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/extensions/HostAdministrationApi.java
@@ -43,14 +43,14 @@
     *
     * @return the usage information
     */
-   Set<Host> listHosts();
+   Set<? extends Host> listHosts();
 
    /**
     * Retrieves the physical/usage resource on a specific host
     *
     * @return the usage information
     */
-   Set<HostResourceUsage> getHostResourceUsage(String hostId);
+   Set<? extends HostResourceUsage> getHostResourceUsage(String hostId);
 
    /**
     * Allow the specified host to accept new instances.
diff --git a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/extensions/HostAdministrationAsyncApi.java b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/extensions/HostAdministrationAsyncApi.java
index c46d78e..89ea47f 100644
--- a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/extensions/HostAdministrationAsyncApi.java
+++ b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/extensions/HostAdministrationAsyncApi.java
@@ -73,7 +73,7 @@
    @GET
    @SelectJson("hosts")
    @ExceptionParser(ReturnEmptySetOnNotFoundOr404.class)
-   ListenableFuture<Set<Host>> listHosts();
+   ListenableFuture<? extends Set<? extends Host>> listHosts();
 
    /**
     * @see HostAdministrationApi#getHostResourceUsage(String)
@@ -82,7 +82,7 @@
    @Path("/{id}")
    @SelectJson("host")
    @ExceptionParser(ReturnEmptySetOnNotFoundOr404.class)
-   ListenableFuture<Set<HostResourceUsage>> getHostResourceUsage(@PathParam("id") String hostId);
+   ListenableFuture<? extends Set<? extends HostResourceUsage>> getHostResourceUsage(@PathParam("id") String hostId);
 
    /**
     * @see HostAdministrationApi#enableHost(String)
diff --git a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/extensions/HostAggregateApi.java b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/extensions/HostAggregateApi.java
index 74e3c28..61bc112 100644
--- a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/extensions/HostAggregateApi.java
+++ b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/extensions/HostAggregateApi.java
@@ -45,7 +45,7 @@
    /**
     * @return the set of host aggregates.
     */
-   Set<HostAggregate> listAggregates();
+   Set<? extends HostAggregate> listAggregates();
 
    /**
     * Retrieves the details of an aggregate, hosts and metadata included.
diff --git a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/extensions/HostAggregateAsyncApi.java b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/extensions/HostAggregateAsyncApi.java
index 1ea494c..a964b48 100644
--- a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/extensions/HostAggregateAsyncApi.java
+++ b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/extensions/HostAggregateAsyncApi.java
@@ -66,7 +66,7 @@
    @SelectJson("aggregates")
    @Consumes(MediaType.APPLICATION_JSON)
    @ExceptionParser(ReturnEmptySetOnNotFoundOr404.class)
-   ListenableFuture<Set<HostAggregate>> listAggregates();
+   ListenableFuture<? extends Set<? extends HostAggregate>> listAggregates();
 
    /**
     * @see HostAggregateApi#getAggregate(String)
@@ -76,7 +76,7 @@
    @SelectJson("aggregate")
    @Consumes(MediaType.APPLICATION_JSON)
    @ExceptionParser(ReturnNullOnNotFoundOr404.class)
-   ListenableFuture<HostAggregate> getAggregate(@PathParam("id") String id);
+   ListenableFuture<? extends HostAggregate> getAggregate(@PathParam("id") String id);
 
    /**
     * @see HostAggregateApi#createAggregate(String, String)
@@ -86,7 +86,7 @@
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces(MediaType.APPLICATION_JSON)
    @WrapWith("aggregate")
-   ListenableFuture<HostAggregate> createAggregate(@PayloadParam("name") String name,
+   ListenableFuture<? extends HostAggregate> createAggregate(@PayloadParam("name") String name,
                                                    @PayloadParam("availability_zone") String availabilityZone);
 
    /**
@@ -97,7 +97,7 @@
    @SelectJson("aggregate")
    @Consumes(MediaType.APPLICATION_JSON)
    @WrapWith("aggregate")
-   ListenableFuture<HostAggregate> updateName(@PathParam("id") String id, @PayloadParam("name") String name);
+   ListenableFuture<? extends HostAggregate> updateName(@PathParam("id") String id, @PayloadParam("name") String name);
 
    /**
     * @see HostAggregateApi#updateAvailabilityZone
@@ -107,7 +107,7 @@
    @SelectJson("aggregate")
    @Consumes(MediaType.APPLICATION_JSON)
    @WrapWith("aggregate")
-   ListenableFuture<HostAggregate> updateAvailabilityZone(@PathParam("id") String id, @PayloadParam("availability_zone") String availabilityZone);
+   ListenableFuture<? extends HostAggregate> updateAvailabilityZone(@PathParam("id") String id, @PayloadParam("availability_zone") String availabilityZone);
    
    /**
     * @see HostAggregateApi#deleteAggregate(String)
@@ -127,7 +127,7 @@
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces(MediaType.APPLICATION_JSON)
    @WrapWith("add_host")
-   ListenableFuture<HostAggregate> addHost(@PathParam("id") String id, @PayloadParam("host") String host);
+   ListenableFuture<? extends HostAggregate> addHost(@PathParam("id") String id, @PayloadParam("host") String host);
 
 
    /**
@@ -139,7 +139,7 @@
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces(MediaType.APPLICATION_JSON)
    @WrapWith("remove_host")
-   ListenableFuture<HostAggregate> removeHost(@PathParam("id") String id, @PayloadParam("host") String host);
+   ListenableFuture<? extends HostAggregate> removeHost(@PathParam("id") String id, @PayloadParam("host") String host);
 
    /**
     * @see HostAggregateApi#setMetadata
@@ -150,5 +150,5 @@
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces(MediaType.APPLICATION_JSON)
    @WrapWith("set_metadata")
-   ListenableFuture<HostAggregate> setMetadata(@PathParam("id") String id, @PayloadParam("metadata") Map<String, String> metadata);
+   ListenableFuture<? extends HostAggregate> setMetadata(@PathParam("id") String id, @PayloadParam("metadata") Map<String, String> metadata);
 }
diff --git a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/extensions/KeyPairApi.java b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/extensions/KeyPairApi.java
index 083e163..1d5ae3c 100644
--- a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/extensions/KeyPairApi.java
+++ b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/extensions/KeyPairApi.java
@@ -43,7 +43,7 @@
     * 
     * @return all Key Pairs
     */
-   Set<Map<String, KeyPair>> listKeyPairs();
+   Set<? extends Map<String, ? extends KeyPair>> listKeyPairs();
 
    /**
     * Create a Key Pair.
diff --git a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/extensions/KeyPairAsyncApi.java b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/extensions/KeyPairAsyncApi.java
index c433b71..3fb1056 100644
--- a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/extensions/KeyPairAsyncApi.java
+++ b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/extensions/KeyPairAsyncApi.java
@@ -69,7 +69,7 @@
    @SelectJson("keypairs")
    @Consumes(MediaType.APPLICATION_JSON)
    @ExceptionParser(ReturnEmptySetOnNotFoundOr404.class)
-   ListenableFuture<Set<Map<String, KeyPair>>> listKeyPairs();
+   ListenableFuture<? extends Set<? extends Map<String, ? extends KeyPair>>> listKeyPairs();
 
    @POST
    @Path("/os-keypairs")
@@ -77,7 +77,7 @@
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces(MediaType.APPLICATION_JSON)
    @Payload("%7B\"keypair\":%7B\"name\":\"{name}\"%7D%7D")
-   ListenableFuture<KeyPair> createKeyPair(@PayloadParam("name") String name);
+   ListenableFuture<? extends KeyPair> createKeyPair(@PayloadParam("name") String name);
 
    @POST
    @Path("/os-keypairs")
@@ -85,7 +85,7 @@
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces(MediaType.APPLICATION_JSON)
    @Payload("%7B\"keypair\":%7B\"name\":\"{name}\",\"public_key\":\"{publicKey}\"%7D%7D")
-   ListenableFuture<KeyPair> createKeyPairWithPublicKey(@PayloadParam("name") String name,
+   ListenableFuture<? extends KeyPair> createKeyPairWithPublicKey(@PayloadParam("name") String name,
          @PayloadParam("publicKey") String publicKey);
 
    @DELETE
diff --git a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/extensions/QuotaAsyncApi.java b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/extensions/QuotaAsyncApi.java
index 63025ea..b0f6dc7 100644
--- a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/extensions/QuotaAsyncApi.java
+++ b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/extensions/QuotaAsyncApi.java
@@ -64,7 +64,7 @@
    @Consumes(MediaType.APPLICATION_JSON)
    @Path("/{tenant_id}")
    @ExceptionParser(ReturnNullOnNotFoundOr404.class)
-   ListenableFuture<Quotas> getQuotasForTenant(@PathParam("tenant_id") String tenantId);
+   ListenableFuture<? extends Quotas> getQuotasForTenant(@PathParam("tenant_id") String tenantId);
 
    /**
     * @see QuotaApi#updateQuotasForTenant(String, org.jclouds.openstack.nova.v2_0.domain.Quotas)
@@ -83,6 +83,6 @@
    @Consumes(MediaType.APPLICATION_JSON)
    @Path("/{tenant_id}/defaults")
    @ExceptionParser(ReturnNullOnNotFoundOr404.class)
-   ListenableFuture<Quotas> getDefaultQuotasForTenant(@PathParam("tenant_id") String tenantId);
+   ListenableFuture<? extends Quotas> getDefaultQuotasForTenant(@PathParam("tenant_id") String tenantId);
 
 }
diff --git a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/extensions/QuotaClassAsyncApi.java b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/extensions/QuotaClassAsyncApi.java
index 5987bdd..41cfe91 100644
--- a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/extensions/QuotaClassAsyncApi.java
+++ b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/extensions/QuotaClassAsyncApi.java
@@ -65,7 +65,7 @@
    @Consumes(MediaType.APPLICATION_JSON)
    @Path("/{id}")
    @ExceptionParser(ReturnNullOnNotFoundOr404.class)
-   ListenableFuture<QuotaClass> getQuotaClass(@PathParam("id") String id);
+   ListenableFuture<? extends QuotaClass> getQuotaClass(@PathParam("id") String id);
 
    /**
     * @see QuotaClassApi#updateQuotaClass
diff --git a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/extensions/SecurityGroupApi.java b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/extensions/SecurityGroupApi.java
index 078aa8d..8042ad2 100644
--- a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/extensions/SecurityGroupApi.java
+++ b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/extensions/SecurityGroupApi.java
@@ -44,7 +44,7 @@
     * 
     * @return all Floating IPs
     */
-   Set<SecurityGroup> listSecurityGroups();
+   Set<? extends SecurityGroup> listSecurityGroups();
 
    /**
     * Get a specific Security Group
diff --git a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/extensions/SecurityGroupAsyncApi.java b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/extensions/SecurityGroupAsyncApi.java
index 08d3cee..438c85e 100644
--- a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/extensions/SecurityGroupAsyncApi.java
+++ b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/extensions/SecurityGroupAsyncApi.java
@@ -73,7 +73,7 @@
    @Consumes(MediaType.APPLICATION_JSON)
    @Path("/os-security-groups")
    @ExceptionParser(ReturnEmptySetOnNotFoundOr404.class)
-   ListenableFuture<Set<SecurityGroup>> listSecurityGroups();
+   ListenableFuture<? extends Set<? extends SecurityGroup>> listSecurityGroups();
 
    /**
     * @see SecurityGroupApi#getSecurityGroup
@@ -83,7 +83,7 @@
    @SelectJson("security_group")
    @Consumes(MediaType.APPLICATION_JSON)
    @ExceptionParser(ReturnNullOnNotFoundOr404.class)
-   ListenableFuture<SecurityGroup> getSecurityGroup(@PathParam("id") String id);
+   ListenableFuture<? extends SecurityGroup> getSecurityGroup(@PathParam("id") String id);
 
    /**
     * @see SecurityGroupApi#createSecurityGroupWithNameAndDescription
@@ -95,7 +95,7 @@
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces(MediaType.APPLICATION_JSON)
    @Payload("%7B\"security_group\":%7B\"name\":\"{name}\",\"description\":\"{description}\"%7D%7D")
-   ListenableFuture<SecurityGroup> createSecurityGroupWithNameAndDescription(@PayloadParam("name") String name,
+   ListenableFuture<? extends SecurityGroup> createSecurityGroupWithNameAndDescription(@PayloadParam("name") String name,
             @PayloadParam("description") String description);
 
    /**
@@ -117,7 +117,7 @@
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces(MediaType.APPLICATION_JSON)
    @MapBinder(BindSecurityGroupRuleToJsonPayload.class)
-   ListenableFuture<SecurityGroupRule> createSecurityGroupRuleAllowingCidrBlock(
+   ListenableFuture<? extends SecurityGroupRule> createSecurityGroupRuleAllowingCidrBlock(
             @PayloadParam("parent_group_id") String parent_group_id, Ingress ip_protocol,
             @PayloadParam("cidr") String cidr);
 
@@ -131,7 +131,7 @@
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces(MediaType.APPLICATION_JSON)
    @MapBinder(BindSecurityGroupRuleToJsonPayload.class)
-   ListenableFuture<SecurityGroupRule> createSecurityGroupRuleAllowingSecurityGroupId(
+   ListenableFuture<? extends SecurityGroupRule> createSecurityGroupRuleAllowingSecurityGroupId(
             @PayloadParam("parent_group_id") String parent_group_id, Ingress ip_protocol,
             @PayloadParam("group_id") String group_id);
 
diff --git a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/extensions/ServerWithSecurityGroupsAsyncApi.java b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/extensions/ServerWithSecurityGroupsAsyncApi.java
index 54bd577..30b8375 100644
--- a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/extensions/ServerWithSecurityGroupsAsyncApi.java
+++ b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/extensions/ServerWithSecurityGroupsAsyncApi.java
@@ -57,6 +57,6 @@
    @Consumes(MediaType.APPLICATION_JSON)
    @Path("/os-create-server-ext/{id}")
    @ExceptionParser(ReturnNullOnNotFoundOr404.class)
-   ListenableFuture<ServerWithSecurityGroups> getServer(@PathParam("id") String id);
+   ListenableFuture<? extends ServerWithSecurityGroups> getServer(@PathParam("id") String id);
 
 }
diff --git a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/extensions/SimpleTenantUsageApi.java b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/extensions/SimpleTenantUsageApi.java
index eaddaea..d17eb19 100644
--- a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/extensions/SimpleTenantUsageApi.java
+++ b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/extensions/SimpleTenantUsageApi.java
@@ -42,7 +42,7 @@
     *
     * @return the set of TenantUsage reports
     */
-   Set<SimpleTenantUsage> listTenantUsages();
+   Set<? extends SimpleTenantUsage> listTenantUsages();
 
    /**
     * Retrieve tenant_usage for a specified tenant
diff --git a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/extensions/SimpleTenantUsageAsyncApi.java b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/extensions/SimpleTenantUsageAsyncApi.java
index 4ef2626..729f50e 100644
--- a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/extensions/SimpleTenantUsageAsyncApi.java
+++ b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/extensions/SimpleTenantUsageAsyncApi.java
@@ -62,7 +62,7 @@
    @SelectJson("tenant_usages")
    @Consumes(MediaType.APPLICATION_JSON)
    @ExceptionParser(ReturnEmptySetOnNotFoundOr404.class)
-   ListenableFuture<Set<SimpleTenantUsage>> listTenantUsages();
+   ListenableFuture<? extends Set<? extends SimpleTenantUsage>> listTenantUsages();
 
    /**
     * @see SimpleTenantUsageApi#getTenantUsage(String)
@@ -72,6 +72,6 @@
    @SelectJson("tenant_usage")
    @Consumes(MediaType.APPLICATION_JSON)
    @ExceptionParser(ReturnNullOnNotFoundOr404.class)
-   ListenableFuture<SimpleTenantUsage> getTenantUsage(@PathParam("id") String tenantId);
+   ListenableFuture<? extends SimpleTenantUsage> getTenantUsage(@PathParam("id") String tenantId);
 
 }
diff --git a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/extensions/VirtualInterfaceApi.java b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/extensions/VirtualInterfaceApi.java
index 550ddd4..257dea3 100644
--- a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/extensions/VirtualInterfaceApi.java
+++ b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/extensions/VirtualInterfaceApi.java
@@ -41,6 +41,6 @@
     *
     * @return the list of snapshots
     */
-   Set<VirtualInterface> listVirtualInterfacesForServer(String serverId);   
+   Set<? extends VirtualInterface> listVirtualInterfacesForServer(String serverId);   
 
 }
diff --git a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/extensions/VirtualInterfaceAsyncApi.java b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/extensions/VirtualInterfaceAsyncApi.java
index 47f1702..f37bf69 100644
--- a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/extensions/VirtualInterfaceAsyncApi.java
+++ b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/extensions/VirtualInterfaceAsyncApi.java
@@ -56,5 +56,5 @@
    @Consumes(MediaType.APPLICATION_JSON)
    @Path("/servers/{server_id}/os-virtual-interfaces")
    @ExceptionParser(ReturnEmptySetOnNotFoundOr404.class)
-   ListenableFuture<Set<VirtualInterface>> listVirtualInterfacesForServer(@PathParam("server_id") String serverId);
+   ListenableFuture<? extends Set<? extends VirtualInterface>> listVirtualInterfacesForServer(@PathParam("server_id") String serverId);
 }
diff --git a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/extensions/VolumeApi.java b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/extensions/VolumeApi.java
index b4c0225..3e3af64 100644
--- a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/extensions/VolumeApi.java
+++ b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/extensions/VolumeApi.java
@@ -45,14 +45,14 @@
     *
     * @return the list of snapshots
     */
-   Set<Volume> listVolumes();
+   Set<? extends Volume> listVolumes();
 
    /**
     * Returns a detailed list of volumes.
     *
     * @return the list of volumes.
     */
-   Set<Volume> listVolumesInDetail();
+   Set<? extends Volume> listVolumesInDetail();
 
    /**
     * Return data about the given volume.
@@ -80,7 +80,7 @@
     * 
     * @return all Floating IPs
     */
-   Set<VolumeAttachment> listAttachmentsOnServer(String serverId);
+   Set<? extends VolumeAttachment> listAttachmentsOnServer(String serverId);
 
    /**
     * Get a specific attached volume.
@@ -108,14 +108,14 @@
     *
     * @return the list of snapshots
     */
-   Set<VolumeSnapshot> listSnapshots();
+   Set<? extends VolumeSnapshot> listSnapshots();
 
    /**
     * Returns a summary list of snapshots.
     *
     * @return the list of snapshots
     */
-   Set<VolumeSnapshot> listSnapshotsInDetail();
+   Set<? extends VolumeSnapshot> listSnapshotsInDetail();
 
    /**
     * Return data about the given snapshot.
diff --git a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/extensions/VolumeAsyncApi.java b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/extensions/VolumeAsyncApi.java
index 18f680b..412183a 100644
--- a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/extensions/VolumeAsyncApi.java
+++ b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/extensions/VolumeAsyncApi.java
@@ -71,7 +71,7 @@
    @SelectJson("volumes")
    @Consumes(MediaType.APPLICATION_JSON)
    @ExceptionParser(ReturnEmptySetOnNotFoundOr404.class)
-   ListenableFuture<Set<Volume>> listVolumes();
+   ListenableFuture<? extends Set<? extends Volume>> listVolumes();
 
    /**
     * Returns a detailed list of volumes.
@@ -83,7 +83,7 @@
    @SelectJson("volumes")
    @Consumes(MediaType.APPLICATION_JSON)
    @ExceptionParser(ReturnEmptySetOnNotFoundOr404.class)
-   ListenableFuture<Set<Volume>> listVolumesInDetail();
+   ListenableFuture<? extends Set<? extends Volume>> listVolumesInDetail();
 
    /**
     * Return data about the given volume.
@@ -95,7 +95,7 @@
    @SelectJson("volume")
    @Consumes(MediaType.APPLICATION_JSON)
    @ExceptionParser(ReturnNullOnNotFoundOr404.class)
-   ListenableFuture<Volume> getVolume(@PathParam("id") String volumeId);
+   ListenableFuture<? extends Volume> getVolume(@PathParam("id") String volumeId);
 
    /**
     * Creates a new volume
@@ -108,7 +108,7 @@
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces(MediaType.APPLICATION_JSON)
    @MapBinder(CreateVolumeOptions.class)
-   ListenableFuture<Volume> createVolume(@PayloadParam("size") int sizeGB, CreateVolumeOptions... options);
+   ListenableFuture<? extends Volume> createVolume(@PayloadParam("size") int sizeGB, CreateVolumeOptions... options);
 
    /**
     * Delete a volume.
@@ -131,7 +131,7 @@
    @SelectJson("volumeAttachments")
    @Consumes(MediaType.APPLICATION_JSON)
    @ExceptionParser(ReturnEmptySetOnNotFoundOr404.class)
-   ListenableFuture<Set<VolumeAttachment>> listAttachmentsOnServer(@PathParam("server_id") String serverId);
+   ListenableFuture<? extends Set<? extends VolumeAttachment>> listAttachmentsOnServer(@PathParam("server_id") String serverId);
 
    /**
     * Get a specific attached volume.
@@ -143,7 +143,7 @@
    @SelectJson("volumeAttachment")
    @Consumes(MediaType.APPLICATION_JSON)
    @ExceptionParser(ReturnNullOnNotFoundOr404.class)
-   ListenableFuture<VolumeAttachment> getAttachmentForVolumeOnServer(@PathParam("id") String volumeId,
+   ListenableFuture<? extends VolumeAttachment> getAttachmentForVolumeOnServer(@PathParam("id") String volumeId,
                                                                      @PathParam("server_id") String serverId);
 
    /**
@@ -157,7 +157,7 @@
    @Produces(MediaType.APPLICATION_JSON)
    @Consumes(MediaType.APPLICATION_JSON)
    @WrapWith("volumeAttachment")
-   ListenableFuture<VolumeAttachment> attachVolumeToServerAsDevice(@PayloadParam("volumeId") String volumeId,
+   ListenableFuture<? extends VolumeAttachment> attachVolumeToServerAsDevice(@PayloadParam("volumeId") String volumeId,
                                              @PathParam("server_id") String serverId, @PayloadParam("device") String device);
 
    /**
@@ -181,7 +181,7 @@
    @SelectJson("snapshots")
    @Consumes(MediaType.APPLICATION_JSON)
    @ExceptionParser(ReturnEmptySetOnNotFoundOr404.class)
-   ListenableFuture<Set<VolumeSnapshot>> listSnapshots();
+   ListenableFuture<? extends Set<? extends VolumeSnapshot>> listSnapshots();
 
    /**
     * Returns a summary list of snapshots.
@@ -193,7 +193,7 @@
    @SelectJson("snapshots")
    @Consumes(MediaType.APPLICATION_JSON)
    @ExceptionParser(ReturnEmptySetOnNotFoundOr404.class)
-   ListenableFuture<Set<VolumeSnapshot>> listSnapshotsInDetail();
+   ListenableFuture<? extends Set<? extends VolumeSnapshot>> listSnapshotsInDetail();
 
    /**
     * Return data about the given snapshot.
@@ -205,7 +205,7 @@
    @SelectJson("snapshot")
    @Consumes(MediaType.APPLICATION_JSON)
    @ExceptionParser(ReturnNullOnNotFoundOr404.class)
-   ListenableFuture<VolumeSnapshot> getSnapshot(@PathParam("id") String snapshotId);
+   ListenableFuture<? extends VolumeSnapshot> getSnapshot(@PathParam("id") String snapshotId);
 
    /**
     * Creates a new Snapshot
@@ -218,7 +218,7 @@
    @Produces(MediaType.APPLICATION_JSON)
    @Consumes(MediaType.APPLICATION_JSON)
    @MapBinder(CreateVolumeSnapshotOptions.class)
-   ListenableFuture<VolumeSnapshot> createSnapshot(@PayloadParam("volume_id") String volumeId, CreateVolumeSnapshotOptions... options);
+   ListenableFuture<? extends VolumeSnapshot> createSnapshot(@PayloadParam("volume_id") String volumeId, CreateVolumeSnapshotOptions... options);
 
    /**
     * Delete a snapshot.
diff --git a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/extensions/VolumeTypeApi.java b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/extensions/VolumeTypeApi.java
index d7506da..b1225c3 100644
--- a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/extensions/VolumeTypeApi.java
+++ b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/extensions/VolumeTypeApi.java
@@ -47,7 +47,7 @@
    /**
     * @return set of all volume types
     */
-   Set<VolumeType> listVolumeTypes();
+   Set<? extends VolumeType> listVolumeTypes();
 
    /**
     * @param id the id of the volume type to retrieve
diff --git a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/extensions/VolumeTypeAsyncApi.java b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/extensions/VolumeTypeAsyncApi.java
index 2e65e20..e50e172 100644
--- a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/extensions/VolumeTypeAsyncApi.java
+++ b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/extensions/VolumeTypeAsyncApi.java
@@ -72,7 +72,7 @@
    @GET
    @SelectJson("volume_types")
    @ExceptionParser(ReturnEmptySetOnNotFoundOr404.class)
-   ListenableFuture<Set<VolumeType>> listVolumeTypes();
+   ListenableFuture<? extends Set<? extends VolumeType>> listVolumeTypes();
 
 
    /**
@@ -82,7 +82,7 @@
    @Path("/{id}")
    @SelectJson("volume_type")
    @ExceptionParser(ReturnNullOnNotFoundOr404.class)
-   ListenableFuture<VolumeType> getVolumeType(@PathParam("id") String id);
+   ListenableFuture<? extends VolumeType> getVolumeType(@PathParam("id") String id);
 
    /**
     * @see VolumeTypeApi#createVolumeType
@@ -91,7 +91,7 @@
    @SelectJson("volume_type")
    @Produces(MediaType.APPLICATION_JSON)
    @WrapWith("volume_type")
-   ListenableFuture<VolumeType> createVolumeType(@PayloadParam("name") String name, CreateVolumeTypeOptions... options);
+   ListenableFuture<? extends VolumeType> createVolumeType(@PayloadParam("name") String name, CreateVolumeTypeOptions... options);
 
    /**
     * @see VolumeTypeApi#deleteVolumeType
diff --git a/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v2_0/compute/loaders/LoadFloatingIpsForInstanceTest.java b/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v2_0/compute/loaders/LoadFloatingIpsForInstanceTest.java
index 6a7e24c..291d89e 100644
--- a/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v2_0/compute/loaders/LoadFloatingIpsForInstanceTest.java
+++ b/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v2_0/compute/loaders/LoadFloatingIpsForInstanceTest.java
@@ -25,6 +25,8 @@
 import static org.testng.Assert.assertEquals;
 import static org.testng.AssertJUnit.assertFalse;
 
+import java.util.Set;
+
 import org.jclouds.openstack.nova.v2_0.NovaApi;
 import org.jclouds.openstack.nova.v2_0.domain.FloatingIP;
 import org.jclouds.openstack.nova.v2_0.domain.zonescoped.ZoneAndId;
@@ -47,7 +49,7 @@
       FloatingIP testIp = FloatingIP.builder().id("1").ip("1.1.1.1").fixedIp("10.1.1.1").instanceId("i-blah").build();
 
       expect(api.getFloatingIPExtensionForZone("Zone")).andReturn((Optional) Optional.of(ipApi)).atLeastOnce();
-      expect(ipApi.listFloatingIPs()).andReturn(ImmutableSet.<FloatingIP>of(testIp)).atLeastOnce();
+      expect(ipApi.listFloatingIPs()).andReturn((Set) ImmutableSet.<FloatingIP>of(testIp)).atLeastOnce();
 
       replay(api);
       replay(ipApi);
@@ -67,7 +69,7 @@
 
       expect(api.getFloatingIPExtensionForZone("Zone")).andReturn((Optional) Optional.of(ipApi)).atLeastOnce();
 
-      expect(ipApi.listFloatingIPs()).andReturn(ImmutableSet.<FloatingIP>of()).atLeastOnce();
+      expect(ipApi.listFloatingIPs()).andReturn((Set) ImmutableSet.<FloatingIP>of()).atLeastOnce();
 
       replay(api);
       replay(ipApi);
@@ -89,7 +91,7 @@
       expect(api.getFloatingIPExtensionForZone("Zone")).andReturn((Optional) Optional.of(ipApi)).atLeastOnce();
 
       expect(ipApi.listFloatingIPs()).andReturn(
-            ImmutableSet.<FloatingIP>of(FloatingIP.builder().id("1").ip("1.1.1.1").build()))
+            (Set) ImmutableSet.<FloatingIP>of(FloatingIP.builder().id("1").ip("1.1.1.1").build()))
             .atLeastOnce();
 
       replay(api);
diff --git a/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v2_0/extensions/FloatingIPApiLiveTest.java b/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v2_0/extensions/FloatingIPApiLiveTest.java
index 8940b14..a35aaab 100644
--- a/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v2_0/extensions/FloatingIPApiLiveTest.java
+++ b/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v2_0/extensions/FloatingIPApiLiveTest.java
@@ -52,7 +52,7 @@
          if (!apiOption.isPresent())
             continue;
          FloatingIPApi api = apiOption.get();
-         Set<FloatingIP> response = api.listFloatingIPs();
+         Set<? extends FloatingIP> response = api.listFloatingIPs();
          assert null != response;
          assertTrue(response.size() >= 0);
          for (FloatingIP ip : response) {
@@ -77,7 +77,7 @@
          FloatingIP floatingIP = api.allocate();
          assertNotNull(floatingIP);
 
-         Set<FloatingIP> response = api.listFloatingIPs();
+         Set<? extends FloatingIP> response = api.listFloatingIPs();
          boolean ipInSet = false;
          for (FloatingIP ip : response) {
             if (ip.getId().equals(floatingIP.getId()))
diff --git a/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v2_0/extensions/HostAdministrationApiExpectTest.java b/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v2_0/extensions/HostAdministrationApiExpectTest.java
index 8d61689..b824552 100644
--- a/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v2_0/extensions/HostAdministrationApiExpectTest.java
+++ b/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v2_0/extensions/HostAdministrationApiExpectTest.java
@@ -59,7 +59,7 @@
       
       Host expected = Host.builder().name("ubuntu").service("compute").build();
 
-      Set<Host> result = api.listHosts();
+      Set<? extends Host> result = api.listHosts();
       Host host = Iterables.getOnlyElement(result);
       assertEquals(host.getName(), "ubuntu");
       assertEquals(host.getService(), "compute");
diff --git a/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v2_0/extensions/HostAdministrationApiLiveTest.java b/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v2_0/extensions/HostAdministrationApiLiveTest.java
index 88ff7b9..20ce931 100644
--- a/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v2_0/extensions/HostAdministrationApiLiveTest.java
+++ b/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v2_0/extensions/HostAdministrationApiLiveTest.java
@@ -65,7 +65,7 @@
    public void testListAndGet() throws Exception {
       if (optApi.isPresent()) {
          HostAdministrationApi api = optApi.get();
-         Set<Host> hosts = api.listHosts();
+         Set<? extends Host> hosts = api.listHosts();
          assertNotNull(hosts);
          for (Host host : hosts) {
             for (HostResourceUsage usage : api.getHostResourceUsage(host.getName())) {
diff --git a/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v2_0/extensions/HostAggregateApiLiveTest.java b/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v2_0/extensions/HostAggregateApiLiveTest.java
index 2224da4..566c2b3 100644
--- a/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v2_0/extensions/HostAggregateApiLiveTest.java
+++ b/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v2_0/extensions/HostAggregateApiLiveTest.java
@@ -78,7 +78,7 @@
    public void testListAndGetAggregate() {
       if (apiOption.isPresent()) {
          HostAggregateApi api = apiOption.get();
-         Set<HostAggregate> aggregates = api.listAggregates();
+         Set<? extends HostAggregate> aggregates = api.listAggregates();
          for (HostAggregate aggregate : aggregates) {
             assertNotNull(aggregate.getId());
             assertNotNull(aggregate.getName());
diff --git a/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v2_0/extensions/KeyPairApiExpectTest.java b/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v2_0/extensions/KeyPairApiExpectTest.java
index 4e39d89..5f215c3 100644
--- a/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v2_0/extensions/KeyPairApiExpectTest.java
+++ b/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v2_0/extensions/KeyPairApiExpectTest.java
@@ -55,6 +55,7 @@
 
       assertEquals(apiWhenServersExist.getConfiguredZones(), ImmutableSet.of("az-1.region-a.geo-1"));
 
+      // NOTE this required a change to the KeyPair domain object toString method
       assertEquals(apiWhenServersExist.getKeyPairExtensionForZone("az-1.region-a.geo-1").get().listKeyPairs().toString(),
             new ParseKeyPairListTest().expected().toString());
    }
diff --git a/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v2_0/extensions/KeyPairApiLiveTest.java b/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v2_0/extensions/KeyPairApiLiveTest.java
index 300b263..e8f2837 100644
--- a/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v2_0/extensions/KeyPairApiLiveTest.java
+++ b/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v2_0/extensions/KeyPairApiLiveTest.java
@@ -38,7 +38,7 @@
    public void testListKeyPairs() throws Exception {
       for (String zoneId : novaContext.getApi().getConfiguredZones()) {
          KeyPairApi api = novaContext.getApi().getKeyPairExtensionForZone(zoneId).get();
-         Set<Map<String, KeyPair>> keyPairsList = api.listKeyPairs();
+         Set<? extends Map<String, ? extends KeyPair>> keyPairsList = api.listKeyPairs();
          assertNotNull(keyPairsList);
       }
    }
diff --git a/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v2_0/extensions/SecurityGroupApiLiveTest.java b/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v2_0/extensions/SecurityGroupApiLiveTest.java
index 3168930..e6a5a57 100644
--- a/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v2_0/extensions/SecurityGroupApiLiveTest.java
+++ b/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v2_0/extensions/SecurityGroupApiLiveTest.java
@@ -44,7 +44,7 @@
    public void listSecurityGroups() throws Exception {
       for (String zoneId : novaContext.getApi().getConfiguredZones()) {
          SecurityGroupApi api = novaContext.getApi().getSecurityGroupExtensionForZone(zoneId).get();
-         Set<SecurityGroup> securityGroupsList = api.listSecurityGroups();
+         Set<? extends SecurityGroup> securityGroupsList = api.listSecurityGroups();
          assertNotNull(securityGroupsList);
       }
    }
diff --git a/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v2_0/extensions/SimpleTenantUsageApiExpectTest.java b/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v2_0/extensions/SimpleTenantUsageApiExpectTest.java
index 08fef66..e158655 100644
--- a/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v2_0/extensions/SimpleTenantUsageApiExpectTest.java
+++ b/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v2_0/extensions/SimpleTenantUsageApiExpectTest.java
@@ -58,7 +58,7 @@
                   .payload(payloadFromResource("/simple_tenant_usages.json")).build())
             .getSimpleTenantUsageExtensionForZone("az-1.region-a.geo-1").get();
       
-      Set<SimpleTenantUsage> results = api.listTenantUsages();
+      Set<? extends SimpleTenantUsage> results = api.listTenantUsages();
       
       SimpleTenantUsage usage = Iterables.getOnlyElement(results);
       assertEquals(usage.getTenantId(), "f8535069c3fb404cb61c873b1a0b4921");
diff --git a/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v2_0/extensions/SimpleTenantUsageApiLiveTest.java b/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v2_0/extensions/SimpleTenantUsageApiLiveTest.java
index dfa2c66..4fe7a30 100644
--- a/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v2_0/extensions/SimpleTenantUsageApiLiveTest.java
+++ b/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v2_0/extensions/SimpleTenantUsageApiLiveTest.java
@@ -41,7 +41,7 @@
          Optional<? extends SimpleTenantUsageApi> optApi = novaContext.getApi().getSimpleTenantUsageExtensionForZone(zoneId);
          if (optApi.isPresent() && identity.endsWith(":admin")) {
             SimpleTenantUsageApi api = optApi.get();
-            Set<SimpleTenantUsage> usages = api.listTenantUsages();
+            Set<? extends SimpleTenantUsage> usages = api.listTenantUsages();
             assertNotNull(usages);
             for (SimpleTenantUsage usage : usages) {
                SimpleTenantUsage details = api.getTenantUsage(usage.getTenantId());
diff --git a/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v2_0/extensions/VirtualInterfaceApiLiveTest.java b/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v2_0/extensions/VirtualInterfaceApiLiveTest.java
index 1962a0f..f409ea1 100644
--- a/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v2_0/extensions/VirtualInterfaceApiLiveTest.java
+++ b/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v2_0/extensions/VirtualInterfaceApiLiveTest.java
@@ -55,7 +55,7 @@
          Server testServer = null;
          try {
             testServer = createServerInZone(zone);
-            Set<VirtualInterface> results = apiOption.get().listVirtualInterfacesForServer(testServer.getId());
+            Set<? extends VirtualInterface> results = apiOption.get().listVirtualInterfacesForServer(testServer.getId());
             for (VirtualInterface vif : results) {
                assertNotNull(vif.getId());
                assertNotNull(vif.getMacAddress());
diff --git a/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v2_0/extensions/VolumeApiExpectTest.java b/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v2_0/extensions/VolumeApiExpectTest.java
index 9e0d7c5..80bde50 100644
--- a/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v2_0/extensions/VolumeApiExpectTest.java
+++ b/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v2_0/extensions/VolumeApiExpectTest.java
@@ -62,7 +62,7 @@
             HttpResponse.builder().statusCode(200).payload(payloadFromResource("/volume_list.json")).build()
       ).getVolumeExtensionForZone("az-1.region-a.geo-1").get();
 
-      Set<Volume> volumes = api.listVolumes();
+      Set<? extends Volume> volumes = api.listVolumes();
       assertEquals(volumes, ImmutableSet.of(testVolume()));
    }
 
@@ -75,7 +75,7 @@
             HttpResponse.builder().statusCode(404).build()
       ).getVolumeExtensionForZone("az-1.region-a.geo-1").get();
 
-      Set<Volume> volumes = api.listVolumes();
+      Set<? extends Volume> volumes = api.listVolumes();
       assertTrue(volumes.isEmpty());
    }
 
@@ -88,7 +88,7 @@
             HttpResponse.builder().statusCode(200).payload(payloadFromResource("/volume_list_detail.json")).build()
       ).getVolumeExtensionForZone("az-1.region-a.geo-1").get();
 
-      Set<Volume> volumes = api.listVolumesInDetail();
+      Set<? extends Volume> volumes = api.listVolumesInDetail();
       assertEquals(volumes, ImmutableSet.of(testVolume()));
    }
 
@@ -101,7 +101,7 @@
             HttpResponse.builder().statusCode(404).build()
       ).getVolumeExtensionForZone("az-1.region-a.geo-1").get();
 
-      Set<Volume> volumes = api.listVolumesInDetail();
+      Set<? extends Volume> volumes = api.listVolumesInDetail();
       assertTrue(volumes.isEmpty());
    }
    
@@ -203,7 +203,7 @@
             HttpResponse.builder().statusCode(200).payload(payloadFromResource("/attachment_list.json")).build()
       ).getVolumeExtensionForZone("az-1.region-a.geo-1").get();
 
-      Set<VolumeAttachment> attachments = api.listAttachmentsOnServer("instance-1");
+      Set<? extends VolumeAttachment> attachments = api.listAttachmentsOnServer("instance-1");
       assertEquals(attachments, ImmutableSet.of(testAttachment()));
       // double-check individual fields
       VolumeAttachment attachment = Iterables.getOnlyElement(attachments);
@@ -312,7 +312,7 @@
             HttpResponse.builder().statusCode(200).payload(payloadFromResource("/snapshot_list.json")).build()
       ).getVolumeExtensionForZone("az-1.region-a.geo-1").get();
 
-      Set<VolumeSnapshot> snapshots = api.listSnapshots();
+      Set<? extends VolumeSnapshot> snapshots = api.listSnapshots();
       assertEquals(snapshots, ImmutableSet.of(testSnapshot()));
    }
 
@@ -325,7 +325,7 @@
             HttpResponse.builder().statusCode(404).build()
       ).getVolumeExtensionForZone("az-1.region-a.geo-1").get();
 
-      Set<VolumeSnapshot> snapshots = api.listSnapshots();
+      Set<? extends VolumeSnapshot> snapshots = api.listSnapshots();
       assertTrue(snapshots.isEmpty());
    }
 
@@ -363,7 +363,7 @@
             HttpResponse.builder().statusCode(200).payload(payloadFromResource("/snapshot_list_detail.json")).build()
       ).getVolumeExtensionForZone("az-1.region-a.geo-1").get();
 
-      Set<VolumeSnapshot> snapshots = api.listSnapshotsInDetail();
+      Set<? extends VolumeSnapshot> snapshots = api.listSnapshotsInDetail();
       assertEquals(snapshots, ImmutableSet.of(testSnapshot()));
 
       // double-check individual fields
@@ -385,7 +385,7 @@
             HttpResponse.builder().statusCode(404).build()
       ).getVolumeExtensionForZone("az-1.region-a.geo-1").get();
 
-      Set<VolumeSnapshot> snapshots = api.listSnapshotsInDetail();
+      Set<? extends VolumeSnapshot> snapshots = api.listSnapshotsInDetail();
       assertTrue(snapshots.isEmpty());
    }
    
diff --git a/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v2_0/extensions/VolumeApiLiveTest.java b/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v2_0/extensions/VolumeApiLiveTest.java
index cbd1e52..fe10147 100644
--- a/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v2_0/extensions/VolumeApiLiveTest.java
+++ b/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v2_0/extensions/VolumeApiLiveTest.java
@@ -108,7 +108,7 @@
    @Test(dependsOnMethods = "testCreateVolume")
    public void testListVolumes() {
       if (volumeOption.isPresent()) {
-         Set<Volume> volumes = volumeOption.get().listVolumes();
+         Set<? extends Volume> volumes = volumeOption.get().listVolumes();
          assertNotNull(volumes);
          boolean foundIt = false;
          for (Volume vol : volumes) {
@@ -125,7 +125,7 @@
    @Test(dependsOnMethods = "testCreateVolume")
    public void testListVolumesInDetail() {
       if (volumeOption.isPresent()) {
-         Set<Volume> volumes = volumeOption.get().listVolumesInDetail();
+         Set<? extends Volume> volumes = volumeOption.get().listVolumesInDetail();
          assertNotNull(volumes);
          boolean foundIt = false;
          for (Volume vol : volumes) {
@@ -174,7 +174,7 @@
    @Test(dependsOnMethods = "testCreateSnapshot")
    public void testListSnapshots() {
       if (volumeOption.isPresent()) {
-         Set<VolumeSnapshot> snapshots = volumeOption.get().listSnapshots();
+         Set<? extends VolumeSnapshot> snapshots = volumeOption.get().listSnapshots();
          assertNotNull(snapshots);
          boolean foundIt = false;
          for (VolumeSnapshot snap : snapshots) {
@@ -193,7 +193,7 @@
    @Test(dependsOnMethods = "testCreateSnapshot")
    public void testListSnapshotsInDetail() {
       if (volumeOption.isPresent()) {
-         Set<VolumeSnapshot> snapshots = volumeOption.get().listSnapshotsInDetail();
+         Set<? extends VolumeSnapshot> snapshots = volumeOption.get().listSnapshotsInDetail();
          assertNotNull(snapshots);
          boolean foundIt = false;
          for (VolumeSnapshot snap : snapshots) {
@@ -225,7 +225,7 @@
          try {
             final String serverId = server_id = createServerInZone(zone).getId();
 
-            Set<VolumeAttachment> attachments = volumeOption.get().listAttachmentsOnServer(serverId);
+            Set<? extends VolumeAttachment> attachments = volumeOption.get().listAttachmentsOnServer(serverId);
             assertNotNull(attachments);
             final int before = attachments.size();
 
diff --git a/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v2_0/extensions/VolumeTypeApiExpectTest.java b/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v2_0/extensions/VolumeTypeApiExpectTest.java
index f024a98..a62308a 100644
--- a/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v2_0/extensions/VolumeTypeApiExpectTest.java
+++ b/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v2_0/extensions/VolumeTypeApiExpectTest.java
@@ -57,7 +57,7 @@
             HttpResponse.builder().statusCode(200).payload(payloadFromResource("/volume_type_list.json")).build()
       ).getVolumeTypeExtensionForZone("az-1.region-a.geo-1").get();
 
-      Set<VolumeType> types = api.listVolumeTypes();
+      Set<? extends VolumeType> types = api.listVolumeTypes();
       assertEquals(types, ImmutableSet.of(testVolumeType()));
    }
 
diff --git a/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v2_0/extensions/VolumeTypeApiLiveTest.java b/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v2_0/extensions/VolumeTypeApiLiveTest.java
index 9270a2e..6d87e17 100644
--- a/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v2_0/extensions/VolumeTypeApiLiveTest.java
+++ b/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v2_0/extensions/VolumeTypeApiLiveTest.java
@@ -96,7 +96,7 @@
    @Test(dependsOnMethods = "testCreateVolumeType")
    public void testListVolumeTypes() {
       if (volumeTypeOption.isPresent()) {
-         Set<VolumeType> volumeTypes = volumeTypeOption.get().listVolumeTypes();
+         Set<? extends VolumeType> volumeTypes = volumeTypeOption.get().listVolumeTypes();
          assertNotNull(volumeTypes);
          boolean foundIt = false;
          for (VolumeType vt : volumeTypes) {
diff --git a/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v2_0/features/ExtensionApiLiveTest.java b/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v2_0/features/ExtensionApiLiveTest.java
index 066b4e4..9a6d3e9 100644
--- a/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v2_0/features/ExtensionApiLiveTest.java
+++ b/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v2_0/features/ExtensionApiLiveTest.java
@@ -19,7 +19,8 @@
 package org.jclouds.openstack.nova.v2_0.features;
 
 import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertTrue;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertNotNull;
 
 import java.util.Set;
 
@@ -29,35 +30,57 @@
 import org.testng.annotations.Test;
 
 /**
- * Tests behavior of {@code ExtensionApi}
+ * Tests behavior of {@link ExtensionApi}
  * 
  * @author Adrian Cole
  */
 @Test(groups = "live", testName = "ExtensionApiLiveTest")
 public class ExtensionApiLiveTest extends BaseNovaApiLiveTest {
 
-   /**
-    * Tests the listing of Extensions (getExtension() is tested too!)
-    * 
-    * @throws Exception
-    */
-   @Test
-   public void testListExtensions() throws Exception {
-      for (String zoneId : novaContext.getApi().getConfiguredZones()) {
-         ExtensionApi api = novaContext.getApi().getExtensionApiForZone(zoneId);
-         Set<? extends Extension> response = api.listExtensions();
-         assert null != response;
-         assertTrue(response.size() >= 0);
-         for (Extension extension : response) {
-            Extension newDetails = api.getExtensionByAlias(extension.getId());
-            assertEquals(newDetails.getId(), extension.getId());
-            assertEquals(newDetails.getName(), extension.getName());
-            assertEquals(newDetails.getDescription(), extension.getDescription());
-            assertEquals(newDetails.getNamespace(), extension.getNamespace());
-            assertEquals(newDetails.getUpdated(), extension.getUpdated());
-            assertEquals(newDetails.getLinks(), extension.getLinks());
-         }
-      }
-   }
+    /**
+     * Tests the listing of Extensions.
+     * 
+     * @throws Exception
+     */
+    @Test(description = "GET /v${apiVersion}/{tenantId}/extensions")
+    public void testListExtensions() throws Exception {
+       for (String zoneId : zones) {
+          ExtensionApi api = novaContext.getApi().getExtensionApiForZone(zoneId);
+          Set<? extends Extension> response = api.listExtensions();
+          assertNotNull(response);
+          assertFalse(response.isEmpty());
+           for (Extension extension : response) {
+              assertNotNull(extension.getId());
+              assertNotNull(extension.getName());
+              assertNotNull(extension.getDescription());
+              assertNotNull(extension.getNamespace());
+              assertNotNull(extension.getUpdated());
+              assertNotNull(extension.getLinks());
+           }
+       }
+    }
+
+    /**
+     * Tests retrieval of Extensions using their alias.
+     * 
+     * @throws Exception
+     */
+    @Test(description = "GET /v${apiVersion}/{tenantId}/extensions/{alias}", dependsOnMethods = { "testListExtensions" })
+    public void testGetExtensionByAlias() throws Exception {
+       for (String zoneId : zones) {
+           ExtensionApi api = novaContext.getApi().getExtensionApiForZone(zoneId);
+           Set<? extends Extension> response = api.listExtensions();
+           for (Extension extension : response) {
+              Extension details = api.getExtensionByAlias(extension.getId());
+              assertNotNull(details);
+              assertEquals(details.getId(), extension.getId());
+              assertEquals(details.getName(), extension.getName());
+              assertEquals(details.getDescription(), extension.getDescription());
+              assertEquals(details.getNamespace(), extension.getNamespace());
+              assertEquals(details.getUpdated(), extension.getUpdated());
+              assertEquals(details.getLinks(), extension.getLinks());
+           }
+        }
+    }
 
 }
diff --git a/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v2_0/features/FlavorApiLiveTest.java b/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v2_0/features/FlavorApiLiveTest.java
index 87cc77c..6dbdb99 100644
--- a/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v2_0/features/FlavorApiLiveTest.java
+++ b/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v2_0/features/FlavorApiLiveTest.java
@@ -19,6 +19,8 @@
 package org.jclouds.openstack.nova.v2_0.features;
 
 import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertNotNull;
 import static org.testng.Assert.assertTrue;
 
 import java.util.Set;
@@ -29,7 +31,7 @@
 import org.testng.annotations.Test;
 
 /**
- * Tests behavior of {@code FlavorApi}
+ * Tests behavior of {@link FlavorApi}
  * 
  * @author Jeremy Daggett
  */
@@ -37,49 +39,69 @@
 public class FlavorApiLiveTest extends BaseNovaApiLiveTest {
 
    /**
-    * Tests the listing of Flavors (getFlavor() is tested too!)
+    * Tests the listing of Flavors.
     * 
     * @throws Exception
     */
-   @Test
+   @Test(description = "GET /v${apiVersion}/{tenantId}/flavors")
    public void testListFlavors() throws Exception {
-      for (String zoneId : novaContext.getApi().getConfiguredZones()) {
+      for (String zoneId : zones) {
          FlavorApi api = novaContext.getApi().getFlavorApiForZone(zoneId);
          Set<? extends Resource> response = api.listFlavors();
-         assert null != response;
-         assertTrue(response.size() >= 0);
+         assertNotNull(response);
+         assertFalse(response.isEmpty());
          for (Resource flavor : response) {
-            Flavor newDetails = api.getFlavor(flavor.getId());
-            assertEquals(newDetails.getId(), flavor.getId());
-            assertEquals(newDetails.getName(), flavor.getName());
-            assertEquals(newDetails.getLinks(), flavor.getLinks());
+            assertNotNull(flavor.getId());
+            assertNotNull(flavor.getName());
+            assertNotNull(flavor.getLinks());
          }
       }
    }
 
    /**
-    * Tests the listing of Flavors in detail (getFlavor() is tested too!)
+    * Tests the listing of Flavors in detail.
     * 
     * @throws Exception
     */
-   @Test
+   @Test(description = "GET /v${apiVersion}/{tenantId}/flavors/detail")
    public void testListFlavorsInDetail() throws Exception {
-      for (String zoneId : novaContext.getApi().getConfiguredZones()) {
+      for (String zoneId : zones) {
          FlavorApi api = novaContext.getApi().getFlavorApiForZone(zoneId);
          Set<? extends Flavor> response = api.listFlavorsInDetail();
-         assert null != response;
-         assertTrue(response.size() >= 0);
+         assertNotNull(response);
+         assertFalse(response.isEmpty());
          for (Flavor flavor : response) {
-            Flavor newDetails = api.getFlavor(flavor.getId());
-            assertEquals(newDetails.getId(), flavor.getId());
-            assertEquals(newDetails.getName(), flavor.getName());
-            assertEquals(newDetails.getLinks(), flavor.getLinks());
-            assertEquals(newDetails.getRam(), flavor.getRam());
-            assertEquals(newDetails.getDisk(), flavor.getDisk());
-            assertEquals(newDetails.getVcpus(), flavor.getVcpus());
+             assertNotNull(flavor.getId());
+             assertNotNull(flavor.getName());
+             assertNotNull(flavor.getLinks());
+             assertTrue(flavor.getRam() > 0);
+             assertTrue(flavor.getDisk() > 0);
+             assertTrue(flavor.getVcpus() > 0);
          }
       }
+   }
 
+   /**
+    * Tests getting Flavors by id.
+    * 
+    * @throws Exception
+    */
+   @Test(description = "GET /v${apiVersion}/{tenantId}/flavors/{id}", dependsOnMethods = { "testListFlavorsInDetail" })
+   public void testGetFlavorById() throws Exception {
+      for (String zoneId : zones) {
+         FlavorApi api = novaContext.getApi().getFlavorApiForZone(zoneId);
+         Set<? extends Flavor> response = api.listFlavorsInDetail();
+         for (Flavor flavor : response) {
+            Flavor details = api.getFlavor(flavor.getId());
+            assertNotNull(details);
+            assertEquals(details.getId(), flavor.getId());
+            assertEquals(details.getName(), flavor.getName());
+            assertEquals(details.getLinks(), flavor.getLinks());
+            assertEquals(details.getRam(), flavor.getRam());
+            assertEquals(details.getDisk(), flavor.getDisk());
+            assertEquals(details.getVcpus(), flavor.getVcpus());
+         }
+      }
    }
 
 }
diff --git a/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v2_0/features/ImageApiLiveTest.java b/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v2_0/features/ImageApiLiveTest.java
index 0346665..7f9bc2b 100644
--- a/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v2_0/features/ImageApiLiveTest.java
+++ b/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v2_0/features/ImageApiLiveTest.java
@@ -19,6 +19,7 @@
 package org.jclouds.openstack.nova.v2_0.features;
 
 import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
 import static org.testng.Assert.assertNotNull;
 import static org.testng.Assert.assertTrue;
 
@@ -30,52 +31,72 @@
 import org.testng.annotations.Test;
 
 /**
- * Tests behavior of {@code ImageApi}
+ * Tests behavior of {@link ImageApi}
  * 
  * @author Michael Arnold
  */
 @Test(groups = "live", testName = "ImageApiLiveTest")
 public class ImageApiLiveTest extends BaseNovaApiLiveTest {
 
-   @Test
+   @Test(description = "GET /v${apiVersion}/{tenantId}/images")
    public void testListImages() throws Exception {
-      for (String zoneId : novaContext.getApi().getConfiguredZones()) {
+      for (String zoneId : zones) {
          ImageApi api = novaContext.getApi().getImageApiForZone(zoneId);
          Set<? extends Resource> response = api.listImages();
          assertNotNull(response);
-         assertTrue(response.size() >= 0);
+         assertFalse(response.isEmpty());
          for (Resource image : response) {
-            Image newDetails = api.getImage(image.getId());
-            assertNotNull(newDetails);
-            assertEquals(newDetails.getId(), image.getId());
-            assertEquals(newDetails.getName(), image.getName());
-            assertEquals(newDetails.getLinks(), image.getLinks());
+            assertNotNull(image.getId());
+            assertNotNull(image.getName());
+            assertNotNull(image.getLinks());
          }
       }
    }
 
-   @Test
+   @Test(description = "GET /v${apiVersion}/{tenantId}/images/detail")
    public void testListImagesInDetail() throws Exception {
       for (String zoneId : novaContext.getApi().getConfiguredZones()) {
          ImageApi api = novaContext.getApi().getImageApiForZone(zoneId);
          Set<? extends Image> response = api.listImagesInDetail();
          assertNotNull(response);
-         assertTrue(response.size() >= 0);
+         assertFalse(response.isEmpty());
          for (Image image : response) {
-            Image newDetails = api.getImage(image.getId());
-            assertNotNull(newDetails);
-            assertEquals(newDetails.getId(), image.getId());
-            assertEquals(newDetails.getName(), image.getName());
-            assertEquals(newDetails.getLinks(), image.getLinks());
-            assertEquals(newDetails.getCreated(), image.getCreated());
-            assertEquals(newDetails.getMinDisk(), image.getMinDisk());
-            assertEquals(newDetails.getMinRam(), image.getMinRam());
-            assertEquals(newDetails.getProgress(), image.getProgress());
-            assertEquals(newDetails.getStatus(), image.getStatus());
-            assertEquals(newDetails.getServer(), image.getServer());
-            assertEquals(newDetails.getTenantId(), image.getTenantId());
-            assertEquals(newDetails.getUpdated(), image.getUpdated());
-            assertEquals(newDetails.getUserId(), image.getUserId());
+            assertNotNull(image.getId());
+            assertNotNull(image.getName());
+            assertNotNull(image.getLinks());
+            assertNotNull(image.getCreated());
+            assertTrue(image.getMinDisk() > 0);
+            assertTrue(image.getMinRam() > 0);
+            assertTrue(image.getProgress() >= 0 && image.getProgress() <= 100);
+            assertNotNull(image.getStatus());
+            assertNotNull(image.getServer());
+            assertNotNull(image.getTenantId());
+            assertNotNull(image.getUpdated());
+            assertNotNull(image.getUserId());
+         }
+      }
+   }
+
+   @Test(description = "GET /v${apiVersion}/{tenantId}/images/{id}", dependsOnMethods = { "testListImagesInDetail" })
+   public void testGetImageById() throws Exception {
+      for (String zoneId : novaContext.getApi().getConfiguredZones()) {
+         ImageApi api = novaContext.getApi().getImageApiForZone(zoneId);
+         Set<? extends Image> response = api.listImagesInDetail();
+         for (Image image : response) {
+            Image details = api.getImage(image.getId());
+            assertNotNull(details);
+            assertEquals(details.getId(), image.getId());
+            assertEquals(details.getName(), image.getName());
+            assertEquals(details.getLinks(), image.getLinks());
+            assertEquals(details.getCreated(), image.getCreated());
+            assertEquals(details.getMinDisk(), image.getMinDisk());
+            assertEquals(details.getMinRam(), image.getMinRam());
+            assertEquals(details.getProgress(), image.getProgress());
+            assertEquals(details.getStatus(), image.getStatus());
+            assertEquals(details.getServer(), image.getServer());
+            assertEquals(details.getTenantId(), image.getTenantId());
+            assertEquals(details.getUpdated(), image.getUpdated());
+            assertEquals(details.getUserId(), image.getUserId());
          }
       }
    }
diff --git a/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v2_0/features/ServerApiLiveTest.java b/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v2_0/features/ServerApiLiveTest.java
index f15604d..b8d78ed 100644
--- a/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v2_0/features/ServerApiLiveTest.java
+++ b/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v2_0/features/ServerApiLiveTest.java
@@ -19,41 +19,79 @@
 package org.jclouds.openstack.nova.v2_0.features;
 
 import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertTrue;
+import static org.testng.Assert.*;
 
 import java.util.Set;
 
 import org.jclouds.openstack.nova.v2_0.domain.Server;
 import org.jclouds.openstack.nova.v2_0.internal.BaseNovaApiLiveTest;
+import org.jclouds.openstack.v2_0.domain.Link.Relation;
 import org.jclouds.openstack.v2_0.domain.Resource;
+import org.jclouds.openstack.v2_0.predicates.LinkPredicates;
 import org.testng.annotations.Test;
 
+import com.google.common.collect.Iterables;
+
 /**
- * Tests behavior of {@code ServerApi}
+ * Tests behavior of {@link ServerApi}
  * 
  * @author Adrian Cole
  */
 @Test(groups = "live", testName = "ServerApiLiveTest")
 public class ServerApiLiveTest extends BaseNovaApiLiveTest {
 
-   @Test
-   public void testListServersInDetail() throws Exception {
-      for (String zoneId : novaContext.getApi().getConfiguredZones()) {
-         ServerApi api = novaContext.getApi().getServerApiForZone(zoneId);
-         Set<? extends Resource> response = api.listServers();
-         assert null != response;
-         assertTrue(response.size() >= 0);
-         for (Resource server : response) {
-            Server newDetails = api.getServer(server.getId());
-            assertEquals(newDetails.getId(), server.getId());
-            assertEquals(newDetails.getName(), server.getName());
-            assertEquals(newDetails.getLinks(), server.getLinks());
-            checkServer(newDetails);
-         }
-      }
-   }
+    @Test(description = "GET /v${apiVersion}/{tenantId}/servers")
+    public void testListServers() throws Exception {
+       for (String zoneId : zones) {
+          ServerApi api = novaContext.getApi().getServerApiForZone(zoneId);
+          Set<? extends Resource> response = api.listServers();
+          assertNotNull(response);
+          assertFalse(response.isEmpty());
+          assert null != response;
+          assertTrue(response.size() >= 0);
+          for (Resource server : response) {
+             checkResource(server);
+          }
+       }
+    }
 
-   private void checkServer(Server server) {
-      assert server.getAddresses().size() > 0 : server;
-   }
+    @Test(description = "GET /v${apiVersion}/{tenantId}/servers/detail")
+    public void testListServersInDetail() throws Exception {
+       for (String zoneId : zones) {
+          ServerApi api = novaContext.getApi().getServerApiForZone(zoneId);
+          Set<? extends Server> response = api.listServersInDetail();
+          assertNotNull(response);
+          assertFalse(response.isEmpty());
+          for (Server server : response) {
+             checkServer(server);
+          }
+       }
+    }
+
+    @Test(description = "GET /v${apiVersion}/{tenantId}/servers/{id}", dependsOnMethods = { "testListServersInDetail" })
+    public void testGetServerById() throws Exception {
+       for (String zoneId : zones) {
+          ServerApi api = novaContext.getApi().getServerApiForZone(zoneId);
+          Set<? extends Resource> response = api.listServers();
+          for (Resource server : response) {
+             Server details = api.getServer(server.getId());
+             assertEquals(details.getId(), server.getId());
+             assertEquals(details.getName(), server.getName());
+             assertEquals(details.getLinks(), server.getLinks());
+             checkServer(details);
+          }
+       }
+    }
+
+    private void checkResource(Resource resource) {
+       assertNotNull(resource.getId());
+       assertNotNull(resource.getName());
+       assertNotNull(resource.getLinks());
+       assertTrue(Iterables.any(resource.getLinks(), LinkPredicates.relationEquals(Relation.SELF)));
+    }
+
+    private void checkServer(Server server) {
+       checkResource(server);
+       assertFalse(server.getAddresses().isEmpty());
+    }
 }
diff --git a/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v2_0/internal/BaseNovaApiLiveTest.java b/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v2_0/internal/BaseNovaApiLiveTest.java
index 3b48732..2d90bd1 100644
--- a/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v2_0/internal/BaseNovaApiLiveTest.java
+++ b/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v2_0/internal/BaseNovaApiLiveTest.java
@@ -19,11 +19,12 @@
 package org.jclouds.openstack.nova.v2_0.internal;
 
 import java.util.Properties;
+import java.util.Set;
 
 import org.jclouds.compute.internal.BaseComputeServiceContextLiveTest;
 import org.jclouds.openstack.keystone.v2_0.config.KeystoneProperties;
-import org.jclouds.openstack.nova.v2_0.NovaAsyncApi;
 import org.jclouds.openstack.nova.v2_0.NovaApi;
+import org.jclouds.openstack.nova.v2_0.NovaAsyncApi;
 import org.jclouds.openstack.nova.v2_0.config.NovaProperties;
 import org.jclouds.openstack.nova.v2_0.domain.Flavor;
 import org.jclouds.openstack.nova.v2_0.domain.Server;
@@ -54,13 +55,15 @@
       provider = "openstack-nova";
    }
 
+   protected Set<String> zones;
    protected RestContext<NovaApi, NovaAsyncApi> novaContext;
 
-   @BeforeGroups(groups = { "integration", "live" })
+   @BeforeGroups(groups = { "integration", "live" }, alwaysRun = true)
    @Override
    public void setupContext() {
       super.setupContext();
       novaContext = view.unwrap();
+      zones = novaContext.getApi().getConfiguredZones();
    }
 
    @Override
diff --git a/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v2_0/parse/ParseKeyPairListTest.java b/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v2_0/parse/ParseKeyPairListTest.java
index 0cd7354..bc30d5b 100644
--- a/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v2_0/parse/ParseKeyPairListTest.java
+++ b/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v2_0/parse/ParseKeyPairListTest.java
@@ -18,7 +18,6 @@
  */
 package org.jclouds.openstack.nova.v2_0.parse;
 
-import java.util.HashMap;
 import java.util.Map;
 import java.util.Set;
 
@@ -33,6 +32,7 @@
 import org.testng.annotations.Test;
 
 import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Maps;
 import com.google.inject.Guice;
 import com.google.inject.Injector;
 
@@ -52,7 +52,7 @@
    @SelectJson("keypairs")
    @Consumes(MediaType.APPLICATION_JSON)
    public Set<Map<String, KeyPair>> expected() {
-      Map<String, KeyPair> kp1 = new HashMap<String, KeyPair>();
+      Map<String, KeyPair> kp1 = Maps.newHashMap();
       kp1.put(
             "keypair",
             KeyPair
@@ -60,7 +60,7 @@
                   .publicKey(
                         "ssh-rsa AAAXB3NzaC1yc2EAAAADAQABAAAAgQCy9EC3O7Ff80vPEfAHDQob61PGwcpYc5KE7tEZnZhrB9n0NyHPRm0E0M+ls3fcTa04HDi+R0DzmRwoyhHQJyI658v8kWZZcuvFjKCcsgsSh/dzdX0xTreLIzSOzt5U7RnZYfshP5cmxtF99yrEY3M/swdin0L+fXsTSkR1B42STQ== nova@nv-aw2az1-api0001")
                   .name("default").fingerprint("ab:0c:f4:f3:54:c0:5d:3f:ed:62:ad:d3:94:7c:79:7c").build());
-      Map<String, KeyPair> kp2 = new HashMap<String, KeyPair>();
+      Map<String, KeyPair> kp2 = Maps.newHashMap();
       kp2.put(
             "keypair",
             KeyPair
diff --git a/apis/swift/src/main/java/org/jclouds/openstack/swift/CommonSwiftAsyncClient.java b/apis/swift/src/main/java/org/jclouds/openstack/swift/CommonSwiftAsyncClient.java
index 71aae2d..b7a9b9f 100644
--- a/apis/swift/src/main/java/org/jclouds/openstack/swift/CommonSwiftAsyncClient.java
+++ b/apis/swift/src/main/java/org/jclouds/openstack/swift/CommonSwiftAsyncClient.java
@@ -35,10 +35,13 @@
 import org.jclouds.blobstore.domain.PageSet;
 import org.jclouds.blobstore.functions.ReturnFalseOnContainerNotFound;
 import org.jclouds.blobstore.functions.ReturnFalseOnKeyNotFound;
+import org.jclouds.blobstore.functions.ReturnNullOnContainerNotFound;
 import org.jclouds.blobstore.functions.ReturnNullOnKeyNotFound;
 import org.jclouds.http.functions.ParseETagHeader;
 import org.jclouds.http.options.GetOptions;
 import org.jclouds.openstack.filters.AuthenticateRequest;
+import org.jclouds.openstack.swift.binders.BindIterableToHeadersWithContainerDeleteMetadataPrefix;
+import org.jclouds.openstack.swift.binders.BindMapToHeadersWithContainerMetadataPrefix;
 import org.jclouds.openstack.swift.binders.BindSwiftObjectMetadataToRequest;
 import org.jclouds.openstack.swift.domain.AccountMetadata;
 import org.jclouds.openstack.swift.domain.ContainerMetadata;
@@ -47,14 +50,26 @@
 import org.jclouds.openstack.swift.domain.SwiftObject;
 import org.jclouds.openstack.swift.functions.ObjectName;
 import org.jclouds.openstack.swift.functions.ParseAccountMetadataResponseFromHeaders;
+import org.jclouds.openstack.swift.functions.ParseContainerMetadataFromHeaders;
 import org.jclouds.openstack.swift.functions.ParseObjectFromHeadersAndHttpContent;
 import org.jclouds.openstack.swift.functions.ParseObjectInfoFromHeaders;
 import org.jclouds.openstack.swift.functions.ParseObjectInfoListFromJsonResponse;
 import org.jclouds.openstack.swift.functions.ReturnTrueOn404FalseOn409;
+import org.jclouds.openstack.swift.options.CreateContainerOptions;
 import org.jclouds.openstack.swift.options.ListContainerOptions;
-import org.jclouds.rest.annotations.*;
+import org.jclouds.openstack.swift.reference.SwiftHeaders;
+import org.jclouds.rest.annotations.BinderParam;
+import org.jclouds.rest.annotations.Endpoint;
+import org.jclouds.rest.annotations.ExceptionParser;
+import org.jclouds.rest.annotations.Headers;
+import org.jclouds.rest.annotations.ParamParser;
+import org.jclouds.rest.annotations.QueryParams;
+import org.jclouds.rest.annotations.RequestFilters;
+import org.jclouds.rest.annotations.ResponseParser;
+import org.jclouds.rest.annotations.SkipEncoding;
 import org.jclouds.rest.functions.ReturnVoidOnNotFoundOr404;
 
+import com.google.common.annotations.Beta;
 import com.google.common.util.concurrent.ListenableFuture;
 import com.google.inject.Provides;
 
@@ -90,12 +105,49 @@
    ListenableFuture<? extends Set<ContainerMetadata>> listContainers(ListContainerOptions... options);
 
    /**
+    * @see CommonSwiftClient#getContainerMetadata
+    */
+   @Beta
+   @HEAD
+   @ResponseParser(ParseContainerMetadataFromHeaders.class)
+   @ExceptionParser(ReturnNullOnContainerNotFound.class)
+   @Path("/{container}")
+   ListenableFuture<ContainerMetadata> getContainerMetadata(@PathParam("container") String container);
+
+   /**
+    * @see CommonSwiftClient#setContainerMetadata
+    */
+   @POST
+   @Path("/{container}")
+   @ExceptionParser(ReturnFalseOnContainerNotFound.class)
+   ListenableFuture<Boolean> setContainerMetadata(@PathParam("container") String container, 
+                                                  @BinderParam(BindMapToHeadersWithContainerMetadataPrefix.class) Map<String, String> containerMetadata);
+
+   /**
+    * @see CommonSwiftClient#deleteContainerMetadata
+    */
+   @POST
+   @Path("/{container}")
+   @ExceptionParser(ReturnFalseOnContainerNotFound.class)
+   ListenableFuture<Boolean> deleteContainerMetadata(@PathParam("container") String container, 
+                                                     @BinderParam(BindIterableToHeadersWithContainerDeleteMetadataPrefix.class) Iterable<String> metadataKeys);
+
+   /**
+    * @see CommonSwiftClient#createContainer
+    */
+   @PUT
+   @Path("/{container}")
+   ListenableFuture<Boolean> createContainer(@PathParam("container") String container,
+                                             CreateContainerOptions... options);
+
+   /**
     * @see CommonSwiftClient#setObjectInfo
     */
    @POST
    @Path("/{container}/{name}")
-   ListenableFuture<Boolean> setObjectInfo(@PathParam("container") String container, @PathParam("name") String name,
-            @BinderParam(BindMapToHeadersWithPrefix.class) Map<String, String> userMetadata);
+   ListenableFuture<Boolean> setObjectInfo(@PathParam("container") String container, 
+                                           @PathParam("name") String name,
+                                           @BinderParam(BindMapToHeadersWithPrefix.class) Map<String, String> userMetadata);
 
    /**
     * @see CommonSwiftClient#createContainer
@@ -120,7 +172,7 @@
    @ResponseParser(ParseObjectInfoListFromJsonResponse.class)
    @Path("/{container}")
    ListenableFuture<PageSet<ObjectInfo>> listObjects(@PathParam("container") String container,
-            ListContainerOptions... options);
+                                                     ListContainerOptions... options);
 
    /**
     * @see CommonSwiftClient#containerExists
@@ -136,9 +188,20 @@
    @PUT
    @Path("/{container}/{name}")
    @ResponseParser(ParseETagHeader.class)
-   ListenableFuture<String> putObject(
-            @PathParam("container") String container,
-            @PathParam("name") @ParamParser(ObjectName.class) @BinderParam(BindSwiftObjectMetadataToRequest.class) SwiftObject object);
+   ListenableFuture<String> putObject(@PathParam("container") String container,
+                                      @PathParam("name") @ParamParser(ObjectName.class) @BinderParam(BindSwiftObjectMetadataToRequest.class) SwiftObject object);
+
+   /**
+    * @see CommonSwiftClient#copyObject
+    */
+   @PUT
+   @Path("/{destinationContainer}/{destinationObject}")
+   @Headers(keys = SwiftHeaders.OBJECT_COPY_FROM, values = "/{sourceContainer}/{sourceObject}")
+   @ExceptionParser(ReturnFalseOnContainerNotFound.class)
+   ListenableFuture<Boolean> copyObject(@PathParam("sourceContainer") String sourceContainer,
+                                        @PathParam("sourceObject") String sourceObject,
+                                        @PathParam("destinationContainer") String destinationContainer,
+                                        @PathParam("destinationObject") String destinationObject);
 
    /**
     * @see CommonSwiftClient#getObject
@@ -147,8 +210,9 @@
    @ResponseParser(ParseObjectFromHeadersAndHttpContent.class)
    @ExceptionParser(ReturnNullOnKeyNotFound.class)
    @Path("/{container}/{name}")
-   ListenableFuture<SwiftObject> getObject(@PathParam("container") String container, @PathParam("name") String name,
-            GetOptions... options);
+   ListenableFuture<SwiftObject> getObject(@PathParam("container") String container, 
+                                           @PathParam("name") String name,
+                                           GetOptions... options);
 
    /**
     * @see CommonSwiftClient#getObjectInfo
@@ -158,7 +222,7 @@
    @ExceptionParser(ReturnNullOnKeyNotFound.class)
    @Path("/{container}/{name}")
    ListenableFuture<MutableObjectInfoWithMetadata> getObjectInfo(@PathParam("container") String container,
-            @PathParam("name") String name);
+                                                                 @PathParam("name") String name);
 
    /**
     * @see CommonSwiftClient#objectExists
@@ -166,7 +230,8 @@
    @HEAD
    @ExceptionParser(ReturnFalseOnKeyNotFound.class)
    @Path("/{container}/{name}")
-   ListenableFuture<Boolean> objectExists(@PathParam("container") String container, @PathParam("name") String name);
+   ListenableFuture<Boolean> objectExists(@PathParam("container") String container, 
+                                          @PathParam("name") String name);
 
    /**
     * @see CommonSwiftClient#removeObject
@@ -174,13 +239,14 @@
    @DELETE
    @ExceptionParser(ReturnVoidOnNotFoundOr404.class)
    @Path("/{container}/{name}")
-   ListenableFuture<Void> removeObject(@PathParam("container") String container, @PathParam("name") String name);
+   ListenableFuture<Void> removeObject(@PathParam("container") String container, 
+                                       @PathParam("name") String name);
 
    @PUT
    @Path("/{container}/{name}")
    @ResponseParser(ParseETagHeader.class)
    @Headers(keys = "X-Object-Manifest", values="{container}/{name}")
    ListenableFuture<String> putObjectManifest(@PathParam("container") String container,
-                                            @PathParam("name") String name);
+                                              @PathParam("name") String name);
 
 }
diff --git a/apis/swift/src/main/java/org/jclouds/openstack/swift/CommonSwiftClient.java b/apis/swift/src/main/java/org/jclouds/openstack/swift/CommonSwiftClient.java
index 4f691a5..730e455 100644
--- a/apis/swift/src/main/java/org/jclouds/openstack/swift/CommonSwiftClient.java
+++ b/apis/swift/src/main/java/org/jclouds/openstack/swift/CommonSwiftClient.java
@@ -31,6 +31,7 @@
 import org.jclouds.openstack.swift.domain.MutableObjectInfoWithMetadata;
 import org.jclouds.openstack.swift.domain.ObjectInfo;
 import org.jclouds.openstack.swift.domain.SwiftObject;
+import org.jclouds.openstack.swift.options.CreateContainerOptions;
 import org.jclouds.openstack.swift.options.ListContainerOptions;
 
 import com.google.inject.Provides;
@@ -87,24 +88,38 @@
     */
    Set<ContainerMetadata> listContainers(ListContainerOptions... options);
 
-   boolean setObjectInfo(String container, String name, Map<String, String> userMetadata);
+   ContainerMetadata getContainerMetadata(String container);
+   
+   boolean setContainerMetadata(String container, Map<String, String> containerMetadata);
+   
+   boolean deleteContainerMetadata(String container, Iterable<String> metadataKeys);
 
    boolean createContainer(String container);
 
+   boolean createContainer(String container, CreateContainerOptions... options);
+   
    boolean deleteContainerIfEmpty(String container);
 
-   PageSet<ObjectInfo> listObjects(String container, ListContainerOptions... options);
-
    boolean containerExists(String container);
 
-   @Timeout(duration = 5 * 1024 * 1024 / 128, timeUnit = TimeUnit.SECONDS)
-   String putObject(String container, SwiftObject object);
+   PageSet<ObjectInfo> listObjects(String container, ListContainerOptions... options);
 
    @Timeout(duration = 5 * 1024 * 1024 / 512, timeUnit = TimeUnit.SECONDS)
    SwiftObject getObject(String container, String name, GetOptions... options);
 
+   boolean setObjectInfo(String container, String name, Map<String, String> userMetadata);
+
    MutableObjectInfoWithMetadata getObjectInfo(String container, String name);
 
+   @Timeout(duration = 5 * 1024 * 1024 / 128, timeUnit = TimeUnit.SECONDS)
+   String putObject(String container, SwiftObject object);
+
+   /**
+    * @return True If the object was copied
+    * @throws CopyObjectException If the object was not copied
+    */
+   boolean copyObject(String sourceContainer, String sourceObject, String destinationContainer, String destinationObject);
+   
    void removeObject(String container, String name);
 
    /**
diff --git a/apis/swift/src/main/java/org/jclouds/openstack/swift/CopyObjectException.java b/apis/swift/src/main/java/org/jclouds/openstack/swift/CopyObjectException.java
new file mode 100644
index 0000000..276bc8e
--- /dev/null
+++ b/apis/swift/src/main/java/org/jclouds/openstack/swift/CopyObjectException.java
@@ -0,0 +1,59 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.openstack.swift;
+
+import org.jclouds.rest.ResourceNotFoundException;
+
+/**
+ * Thrown when an object cannot be copied.
+ * 
+ * @author Everett Toews
+ */
+public class CopyObjectException extends ResourceNotFoundException {
+
+   private String sourcePath;
+   private String destinationPath;
+
+   public CopyObjectException() {
+      super();
+   }
+
+   public CopyObjectException(String sourcePath, String destinationPath, String message) {
+      super(String.format("Either the source path %s or the destination path %s was not found. " +
+      		"(message: %s)", sourcePath, destinationPath, message));
+      this.sourcePath = sourcePath;
+      this.destinationPath = destinationPath;
+   }
+
+   public CopyObjectException(Exception from) {
+      super(from);
+   }
+
+   public String getSourcePath() {
+      return sourcePath;
+   }
+
+   public String getDestinationPath() {
+      return destinationPath;
+   }
+
+   /** The serialVersionUID */
+   private static final long serialVersionUID = -2272965726680721281L;
+
+}
diff --git a/apis/swift/src/main/java/org/jclouds/openstack/swift/binders/BindIterableToHeadersWithContainerDeleteMetadataPrefix.java b/apis/swift/src/main/java/org/jclouds/openstack/swift/binders/BindIterableToHeadersWithContainerDeleteMetadataPrefix.java
new file mode 100644
index 0000000..dd9aef7
--- /dev/null
+++ b/apis/swift/src/main/java/org/jclouds/openstack/swift/binders/BindIterableToHeadersWithContainerDeleteMetadataPrefix.java
@@ -0,0 +1,72 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.openstack.swift.binders;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import javax.inject.Singleton;
+
+import org.jclouds.http.HttpRequest;
+import org.jclouds.openstack.swift.reference.SwiftHeaders;
+import org.jclouds.rest.Binder;
+
+import com.google.common.base.Function;
+import com.google.common.collect.HashMultimap;
+import com.google.common.collect.Iterables;
+
+/**
+ * @author Everett Toews
+ */
+@Singleton
+public class BindIterableToHeadersWithContainerDeleteMetadataPrefix implements Binder {
+   private final Function<String, String> FN;
+
+   public BindIterableToHeadersWithContainerDeleteMetadataPrefix() {
+      FN = new Function<String, String>() {
+
+         @Override
+         public String apply(String element) {
+            String inLowercase = element.toLowerCase();
+            return (inLowercase.startsWith(SwiftHeaders.CONTAINER_DELETE_METADATA_PREFIX)) ? inLowercase : SwiftHeaders.CONTAINER_DELETE_METADATA_PREFIX + inLowercase;
+         }
+
+         @Override
+         public String toString() {
+            return "prefix: " + SwiftHeaders.CONTAINER_DELETE_METADATA_PREFIX;
+         }
+      };
+   }
+
+   @SuppressWarnings("unchecked")
+   @Override
+   public <R extends HttpRequest> R bindToRequest(R request, Object input) {
+      checkArgument(checkNotNull(input, "input") instanceof Iterable<?>, "this binder is only valid for Iterable!");
+      checkNotNull(request, "request");
+
+      Iterable<String> metadataKeys = Iterables.transform((Iterable<String>) input, FN);
+      HashMultimap<String, String> headers = HashMultimap.create();
+      
+      for (String metadataKey: metadataKeys) {
+    	  headers.put(metadataKey, "");
+      }
+      
+      return (R) request.toBuilder().replaceHeaders(headers).build();
+   }
+}
diff --git a/apis/swift/src/main/java/org/jclouds/openstack/swift/binders/BindMapToHeadersWithContainerMetadataPrefix.java b/apis/swift/src/main/java/org/jclouds/openstack/swift/binders/BindMapToHeadersWithContainerMetadataPrefix.java
new file mode 100644
index 0000000..7d25227
--- /dev/null
+++ b/apis/swift/src/main/java/org/jclouds/openstack/swift/binders/BindMapToHeadersWithContainerMetadataPrefix.java
@@ -0,0 +1,11 @@
+package org.jclouds.openstack.swift.binders;
+
+import org.jclouds.blobstore.binders.BindMapToHeadersWithPrefix;
+import org.jclouds.openstack.swift.reference.SwiftHeaders;
+
+public class BindMapToHeadersWithContainerMetadataPrefix extends BindMapToHeadersWithPrefix {
+
+	public BindMapToHeadersWithContainerMetadataPrefix() {
+		super(SwiftHeaders.CONTAINER_METADATA_PREFIX);
+	}
+}
diff --git a/apis/swift/src/main/java/org/jclouds/openstack/swift/functions/ParseContainerMetadataFromHeaders.java b/apis/swift/src/main/java/org/jclouds/openstack/swift/functions/ParseContainerMetadataFromHeaders.java
new file mode 100644
index 0000000..889e2d5
--- /dev/null
+++ b/apis/swift/src/main/java/org/jclouds/openstack/swift/functions/ParseContainerMetadataFromHeaders.java
@@ -0,0 +1,74 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.openstack.swift.functions;
+
+import static com.google.common.base.Preconditions.checkArgument;
+
+import java.util.Map;
+import java.util.Map.Entry;
+
+import org.jclouds.http.HttpRequest;
+import org.jclouds.http.HttpResponse;
+import org.jclouds.openstack.swift.domain.ContainerMetadata;
+import org.jclouds.openstack.swift.reference.SwiftHeaders;
+import org.jclouds.rest.InvocationContext;
+import org.jclouds.rest.internal.GeneratedHttpRequest;
+
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Function;
+import com.google.common.collect.Maps;
+
+/**
+ * This parses @{link {@link org.jclouds.openstack.swift.domain.ContainerMetadata} from
+ * HTTP headers.
+ * 
+ * @author Jeremy Daggett
+ */
+public class ParseContainerMetadataFromHeaders implements Function<HttpResponse, ContainerMetadata>,
+      InvocationContext<ParseContainerMetadataFromHeaders> {
+   private GeneratedHttpRequest request;
+
+   public ContainerMetadata apply(HttpResponse from) {
+      return ContainerMetadata.builder().name(request.getArgs().get(0).toString())
+            .readACL(from.getFirstHeaderOrNull(SwiftHeaders.CONTAINER_READ))
+            .bytes(Long.valueOf(from.getFirstHeaderOrNull(SwiftHeaders.CONTAINER_BYTES_USED)))
+            .count(Long.valueOf(from.getFirstHeaderOrNull(SwiftHeaders.CONTAINER_OBJECT_COUNT)))
+            .metadata(extractUserMetadata(from)).build();
+   }
+
+   
+   @VisibleForTesting
+   Map<String, String> extractUserMetadata(HttpResponse from) {
+      Map<String, String> metadata = Maps.newHashMap();
+      for (Entry<String, String> header : from.getHeaders().entries()) {
+         if (header.getKey() != null && header.getKey().startsWith(SwiftHeaders.CONTAINER_METADATA_PREFIX))
+            metadata.put((header.getKey().substring(SwiftHeaders.CONTAINER_METADATA_PREFIX.length())).toLowerCase(),
+                  header.getValue());
+      }
+      return metadata;
+   }
+   
+   @Override
+   public ParseContainerMetadataFromHeaders setContext(HttpRequest request) {
+      checkArgument(request instanceof GeneratedHttpRequest, "note this handler requires a GeneratedHttpRequest");
+      this.request = (GeneratedHttpRequest) request;
+      return this;
+   }
+
+}
diff --git a/apis/swift/src/main/java/org/jclouds/openstack/swift/handlers/ParseSwiftErrorFromHttpResponse.java b/apis/swift/src/main/java/org/jclouds/openstack/swift/handlers/ParseSwiftErrorFromHttpResponse.java
index 33eef60..d5792d8 100644
--- a/apis/swift/src/main/java/org/jclouds/openstack/swift/handlers/ParseSwiftErrorFromHttpResponse.java
+++ b/apis/swift/src/main/java/org/jclouds/openstack/swift/handlers/ParseSwiftErrorFromHttpResponse.java
@@ -32,6 +32,8 @@
 import org.jclouds.http.HttpResponse;
 import org.jclouds.http.HttpResponseException;
 import org.jclouds.logging.Logger;
+import org.jclouds.openstack.swift.CopyObjectException;
+import org.jclouds.openstack.swift.reference.SwiftHeaders;
 import org.jclouds.rest.AuthorizationException;
 
 /**
@@ -61,10 +63,21 @@
             exception = new AuthorizationException(exception.getMessage(), exception);
             break;
          case 404:
-            if (!command.getCurrentRequest().getMethod().equals("DELETE")) {
+            String sourcePath = command.getCurrentRequest().getFirstHeaderOrNull(SwiftHeaders.OBJECT_COPY_FROM);
+            Exception oldException = exception;
+        	
+            if (sourcePath != null) {
+            	String path = command.getCurrentRequest().getEndpoint().getPath();
+            	int startOfDestinationPath = path.lastIndexOf("/", path.lastIndexOf("/")-1);
+            	String destinationPath = path.substring(startOfDestinationPath);
+            	
+                exception = new CopyObjectException(sourcePath, destinationPath, message);
+                exception.initCause(oldException);
+            }
+            else if (!command.getCurrentRequest().getMethod().equals("DELETE")) {
                String path = command.getCurrentRequest().getEndpoint().getPath();
                Matcher matcher = CONTAINER_PATH.matcher(path);
-               Exception oldException = exception;
+               
                if (matcher.find()) {
                   exception = new ContainerNotFoundException(matcher.group(1), message);
                   exception.initCause(oldException);
diff --git a/apis/swift/src/main/java/org/jclouds/openstack/swift/options/CreateContainerOptions.java b/apis/swift/src/main/java/org/jclouds/openstack/swift/options/CreateContainerOptions.java
new file mode 100644
index 0000000..671d130
--- /dev/null
+++ b/apis/swift/src/main/java/org/jclouds/openstack/swift/options/CreateContainerOptions.java
@@ -0,0 +1,75 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.openstack.swift.options;
+
+import java.util.Map;
+import java.util.Map.Entry;
+
+import org.jclouds.http.options.BaseHttpRequestOptions;
+import org.jclouds.openstack.swift.reference.SwiftHeaders;
+
+/**
+ * Contains options supported in the REST API for the Create Container operation.
+ * 
+ * This specifically enables the Swift ACL for public reads using the 'X-Container-Read'
+ * header. This should be refactored into the Swift API.
+ * 
+ * @author Jeremy Daggett
+ */
+public class CreateContainerOptions extends BaseHttpRequestOptions {
+   public static final CreateContainerOptions NONE = new CreateContainerOptions();
+
+   /**
+    * A name-value pair to associate with the container as metadata.
+    */
+   public CreateContainerOptions withMetadata(Map<String, String> metadata) {
+      for (Entry<String, String> entry : metadata.entrySet()) {
+         if (entry.getKey().startsWith(SwiftHeaders.CONTAINER_METADATA_PREFIX)) {
+            this.headers.put(entry.getKey(), entry.getValue());
+      	 } else {
+            this.headers.put(SwiftHeaders.CONTAINER_METADATA_PREFIX + entry.getKey(), 
+            		    entry.getValue());
+   	     }
+      }
+      return this;
+   }
+   
+
+   /**
+    * Indicates whether a container may be accessed publicly
+    */
+   public CreateContainerOptions withPublicAccess() {
+      this.headers.put(SwiftHeaders.CONTAINER_READ, ".r:*,.rlistings");
+      return this;
+   }
+
+   public static class Builder {
+
+      public static CreateContainerOptions withPublicAccess() {
+         CreateContainerOptions options = new CreateContainerOptions();
+         return options.withPublicAccess();
+      }
+
+      public static CreateContainerOptions withMetadata(Map<String, String> metadata) {
+         CreateContainerOptions options = new CreateContainerOptions();
+         return (CreateContainerOptions) options.withMetadata(metadata);
+      }
+	  
+   }
+}
diff --git a/apis/swift/src/main/java/org/jclouds/openstack/swift/reference/SwiftHeaders.java b/apis/swift/src/main/java/org/jclouds/openstack/swift/reference/SwiftHeaders.java
index 4d73fd1..3e8d37d 100644
--- a/apis/swift/src/main/java/org/jclouds/openstack/swift/reference/SwiftHeaders.java
+++ b/apis/swift/src/main/java/org/jclouds/openstack/swift/reference/SwiftHeaders.java
@@ -29,7 +29,9 @@
    public static final String CONTAINER_BYTES_USED = "X-Container-Bytes-Used";
    public static final String CONTAINER_OBJECT_COUNT = "X-Container-Object-Count";
    public static final String CONTAINER_METADATA_PREFIX = "X-Container-Meta-";
+   public static final String CONTAINER_DELETE_METADATA_PREFIX = "X-Remove-Container-Meta-";
    public static final String USER_METADATA_PREFIX = "X-Object-Meta-";
+   public static final String OBJECT_COPY_FROM = "X-Copy-From";
    
    public static final String CONTAINER_READ = "X-Container-Read";
    public static final String CONTAINER_WRITE = "X-Container-Write";
diff --git a/apis/swift/src/test/java/org/jclouds/openstack/swift/CommonSwiftClientLiveTest.java b/apis/swift/src/test/java/org/jclouds/openstack/swift/CommonSwiftClientLiveTest.java
index 504b833..d1a214e 100644
--- a/apis/swift/src/test/java/org/jclouds/openstack/swift/CommonSwiftClientLiveTest.java
+++ b/apis/swift/src/test/java/org/jclouds/openstack/swift/CommonSwiftClientLiveTest.java
@@ -20,8 +20,10 @@
 
 import static org.jclouds.openstack.swift.options.ListContainerOptions.Builder.underPath;
 import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
 import static org.testng.Assert.assertNotNull;
 import static org.testng.Assert.assertTrue;
+import static org.testng.Assert.fail;
 
 import java.io.ByteArrayInputStream;
 import java.io.IOException;
@@ -274,6 +276,64 @@
       }
    }
 
+   @Test
+   public void testCopyObjectOperations() throws Exception {
+      String sourceContainer = getContainerName();
+      String sourceObject = "original.txt";
+      String sourcePath = "/" + sourceContainer + "/" + sourceObject;
+      String badSource = "badsource";
+      String destinationContainer = getContainerName();
+      String destinationObject = "copy.txt";
+      String destinationPath = "/" + destinationContainer + "/" + destinationObject;
+      String badDestination = "baddestination";
+      String data = "Hello World";
+      SwiftObject sourceSwiftObject = newSwiftObject(data, sourceObject);
+      
+      getApi().putObject(sourceContainer, sourceSwiftObject);
+
+      // test that not giving a destination name *doesn't* copy source name to the destination container with
+      // the source name but copy still returns success :(
+      assertTrue(getApi().copyObject(sourceContainer, sourceObject, destinationContainer, ""));
+      assertTrue(!getApi().objectExists(destinationContainer, sourceObject));
+      
+      // test copy works
+      assertTrue(getApi().copyObject(sourceContainer, sourceObject, destinationContainer, destinationObject));      
+      assertTrue(getApi().objectExists(destinationContainer, destinationObject));
+      
+      SwiftObject destinationSwiftObject = getApi().getObject(destinationContainer, destinationObject);
+      assertEquals(Strings2.toString(destinationSwiftObject.getPayload()), data);
+      
+      // test exception thrown on bad destination container
+      try {
+         assertFalse(getApi().copyObject(sourceContainer, sourceObject, badDestination, destinationObject));
+         fail("Expected CopyObjectException");
+      }
+      catch (CopyObjectException e) {
+         assertEquals(e.getSourcePath(), sourcePath);
+         assertEquals(e.getDestinationPath(), "/" + badDestination + "/" + destinationObject);
+      }
+
+      // test exception thrown on bad source container
+      try {
+          assertFalse(getApi().copyObject(badSource, sourceObject, destinationContainer, destinationObject));
+          fail("Expected CopyObjectException");
+       }
+       catch (CopyObjectException e) {
+          assertEquals(e.getSourcePath(), "/" + badSource + "/" + sourceObject);
+          assertEquals(e.getDestinationPath(), destinationPath);
+       }
+
+      // test exception thrown on bad source name
+      try {
+          assertFalse(getApi().copyObject(sourceContainer, badSource, destinationContainer, destinationObject));
+          fail("Expected CopyObjectException");
+       }
+       catch (CopyObjectException e) {
+          assertEquals(e.getSourcePath(), "/" + sourceContainer + "/" + badSource);
+          assertEquals(e.getDestinationPath(), destinationPath);
+       }
+   }
+   
    protected void testGetObjectContentType(SwiftObject getBlob) {
        String contentType = getBlob.getPayload().getContentMetadata().getContentType();
        assert contentType.startsWith("text/plain") || "application/x-www-form-urlencoded".equals(contentType): contentType;
diff --git a/apis/swift/src/test/java/org/jclouds/openstack/swift/SwiftClientExpectTest.java b/apis/swift/src/test/java/org/jclouds/openstack/swift/SwiftClientExpectTest.java
index 2cf0f55..5395f7d 100644
--- a/apis/swift/src/test/java/org/jclouds/openstack/swift/SwiftClientExpectTest.java
+++ b/apis/swift/src/test/java/org/jclouds/openstack/swift/SwiftClientExpectTest.java
@@ -23,9 +23,14 @@
 
 import org.jclouds.http.HttpRequest;
 import org.jclouds.http.HttpResponse;
+import org.jclouds.http.HttpResponseException;
 import org.jclouds.openstack.swift.internal.BaseSwiftExpectTest;
+import org.jclouds.openstack.swift.reference.SwiftHeaders;
 import org.testng.annotations.Test;
 
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+
 /**
  * 
  * @author Adrian Cole
@@ -33,7 +38,8 @@
 @Test(testName = "SwiftClientExpectTest")
 public class SwiftClientExpectTest extends BaseSwiftExpectTest<SwiftClient> {
 
-   public void testContainerExistsWhenResponseIs2xxReturnsTrue() throws Exception {
+   @Test
+   public void testContainerExistsWhenResponseIs2xxReturnsTrue() {
       HttpRequest headContainer = HttpRequest.builder()
             .method("HEAD")
             .endpoint(swiftEndpointWithHostReplaced + "/foo")
@@ -47,7 +53,8 @@
       assertTrue(clientWhenContainerExists.containerExists("foo"));
    }
 
-   public void testContainerExistsWhenResponseIs404ReturnsFalse() throws Exception {
+   @Test
+   public void testContainerExistsWhenResponseIs404ReturnsFalse() {
       HttpRequest headContainer = HttpRequest.builder()
             .method("HEAD")
             .endpoint(swiftEndpointWithHostReplaced + "/foo")
@@ -59,7 +66,150 @@
             authResponse, headContainer, headContainerResponse);
 
       assertFalse(clientWhenContainerDoesntExist.containerExists("foo"));
-
    }
 
+   @Test
+   public void testSetContainerMetadataWhenResponseIs2xxReturnsTrue() {
+      HttpRequest setContainerMetadataRequest = HttpRequest.builder()
+            .method("POST")
+            .endpoint(swiftEndpointWithHostReplaced + "/foo")
+            .addHeader(SwiftHeaders.CONTAINER_METADATA_PREFIX + "key", "value")
+            .addHeader("X-Auth-Token", authToken).build();
+
+      HttpResponse setContainerMetadataResponse = HttpResponse.builder().statusCode(204).build();
+
+      SwiftClient clientSetContainerMetadata = requestsSendResponses(authRequest,
+            authResponse, setContainerMetadataRequest, setContainerMetadataResponse);
+
+      assertTrue(clientSetContainerMetadata.setContainerMetadata("foo", ImmutableMap.<String, String> of("key", "value")));
+   }
+   
+   @Test(expectedExceptions = HttpResponseException.class)
+   public void testSetContainerMetadataWhenResponseIs400ThrowsException() {
+      HttpRequest setContainerMetadataRequest = HttpRequest.builder()
+              .method("POST")
+              .endpoint(swiftEndpointWithHostReplaced + "/foo")
+              .addHeader(SwiftHeaders.CONTAINER_METADATA_PREFIX, "value")
+              .addHeader("X-Auth-Token", authToken).build();
+
+        HttpResponse setContainerMetadataResponse = HttpResponse.builder()
+              .statusCode(400)
+              .message("Metadata name cannot be empty").build();
+
+        SwiftClient clientSetContainerMetadata = requestsSendResponses(authRequest,
+              authResponse, setContainerMetadataRequest, setContainerMetadataResponse);
+
+        clientSetContainerMetadata.setContainerMetadata("foo", ImmutableMap.<String, String> of("", "value"));
+   }
+
+   @Test
+   public void testSetContainerMetadataWhenResponseIs404ReturnsFalse() {
+      HttpRequest setContainerMetadataRequest = HttpRequest.builder()
+              .method("POST")
+              .endpoint(swiftEndpointWithHostReplaced + "/foo")
+              .addHeader(SwiftHeaders.CONTAINER_METADATA_PREFIX + "key", "value")
+              .addHeader("X-Auth-Token", authToken).build();
+
+        HttpResponse setContainerMetadataResponse = HttpResponse.builder()
+              .statusCode(404).build();
+
+        SwiftClient clientSetContainerMetadata = requestsSendResponses(authRequest,
+              authResponse, setContainerMetadataRequest, setContainerMetadataResponse);
+
+        assertFalse(clientSetContainerMetadata.setContainerMetadata("foo", ImmutableMap.<String, String> of("key", "value")));
+   }
+
+   @Test
+   public void testDeleteContainerMetadataWhenResponseIs2xxReturnsTrue() {
+      HttpRequest deleteContainerMetadataRequest = HttpRequest.builder()
+            .method("POST")
+            .endpoint(swiftEndpointWithHostReplaced + "/foo")
+            .addHeader(SwiftHeaders.CONTAINER_DELETE_METADATA_PREFIX + "bar", "")
+            .addHeader("X-Auth-Token", authToken).build();
+
+      HttpResponse deleteContainerMetadataResponse = HttpResponse.builder().statusCode(204).build();
+
+      SwiftClient clientDeleteContainerMetadata = requestsSendResponses(authRequest,
+            authResponse, deleteContainerMetadataRequest, deleteContainerMetadataResponse);
+
+      assertTrue(clientDeleteContainerMetadata.deleteContainerMetadata("foo", ImmutableList.<String> of("bar")));
+   }
+
+   @Test
+   public void testDeleteContainerMetadataEmptyWhenResponseIs2xxReturnsTrue() {
+      HttpRequest deleteContainerMetadataRequest = HttpRequest.builder()
+            .method("POST")
+            .endpoint(swiftEndpointWithHostReplaced + "/foo")
+            .addHeader(SwiftHeaders.CONTAINER_DELETE_METADATA_PREFIX, "")
+            .addHeader("X-Auth-Token", authToken).build();
+
+      HttpResponse deleteContainerMetadataResponse = HttpResponse.builder().statusCode(204).build();
+
+      SwiftClient clientDeleteContainerMetadata = requestsSendResponses(authRequest,
+            authResponse, deleteContainerMetadataRequest, deleteContainerMetadataResponse);
+
+      assertTrue(clientDeleteContainerMetadata.deleteContainerMetadata("foo", ImmutableList.<String> of("")));
+   }
+
+   @Test
+   public void testDeleteContainerMetadataWhenResponseIs404ReturnsFalse() {
+      HttpRequest deleteContainerMetadataRequest = HttpRequest.builder()
+            .method("POST")
+            .endpoint(swiftEndpointWithHostReplaced + "/foo")
+            .addHeader(SwiftHeaders.CONTAINER_DELETE_METADATA_PREFIX + "bar", "")
+            .addHeader("X-Auth-Token", authToken).build();
+
+      HttpResponse deleteContainerMetadataResponse = HttpResponse.builder().statusCode(404).build();
+
+      SwiftClient clientDeleteContainerMetadata = requestsSendResponses(authRequest,
+            authResponse, deleteContainerMetadataRequest, deleteContainerMetadataResponse);
+
+      assertFalse(clientDeleteContainerMetadata.deleteContainerMetadata("foo", ImmutableList.<String> of("bar")));
+   }
+
+   @Test
+   public void testCopyObjectWhenResponseIs2xxReturnsTrue() {
+      String sourceContainer = "bar";
+      String sourceObject = "foo.txt";
+      String sourcePath = "/" + sourceContainer + "/" + sourceObject;
+      String destinationContainer = "foo";
+      String destinationObject = "bar.txt";
+      String destinationPath = "/" + destinationContainer + "/" + destinationObject;
+		   
+      HttpRequest copyObjectRequest = HttpRequest.builder()
+            .method("PUT")
+            .endpoint(swiftEndpointWithHostReplaced + destinationPath)
+            .addHeader(SwiftHeaders.OBJECT_COPY_FROM, sourcePath)
+            .addHeader("X-Auth-Token", authToken).build();
+
+      HttpResponse copyObjectResponse = HttpResponse.builder().statusCode(201).build();
+
+      SwiftClient clientCopyObject = requestsSendResponses(authRequest,
+            authResponse, copyObjectRequest, copyObjectResponse);
+
+      assertTrue(clientCopyObject.copyObject(sourceContainer, sourceObject, destinationContainer, destinationObject));
+   }
+
+   @Test(expectedExceptions = CopyObjectException.class)
+   public void testCopyObjectWhenResponseIs404ThrowsException() {
+      String sourceContainer = "bar";
+      String sourceObject = "foo.txt";
+      String sourcePath = "/" + sourceContainer + "/" + sourceObject;
+      String destinationContainer = "foo";
+      String destinationObject = "bar.txt";
+      String destinationPath = "/" + destinationContainer + "/" + destinationObject;
+	   
+      HttpRequest copyObjectRequest = HttpRequest.builder()
+            .method("PUT")
+            .endpoint(swiftEndpointWithHostReplaced + destinationPath)
+            .addHeader(SwiftHeaders.OBJECT_COPY_FROM, sourcePath)
+            .addHeader("X-Auth-Token", authToken).build();
+
+      HttpResponse copyObjectResponse = HttpResponse.builder().statusCode(404).build();
+
+      SwiftClient clientCopyObject = requestsSendResponses(authRequest,
+            authResponse, copyObjectRequest, copyObjectResponse);
+
+      assertTrue(clientCopyObject.copyObject(sourceContainer, sourceObject, destinationContainer, destinationObject));
+   }
 }
diff --git a/apis/swift/src/test/java/org/jclouds/openstack/swift/binders/BindIterableToHeadersWithContainerDeleteMetadataPrefixTest.java b/apis/swift/src/test/java/org/jclouds/openstack/swift/binders/BindIterableToHeadersWithContainerDeleteMetadataPrefixTest.java
new file mode 100644
index 0000000..602e73f
--- /dev/null
+++ b/apis/swift/src/test/java/org/jclouds/openstack/swift/binders/BindIterableToHeadersWithContainerDeleteMetadataPrefixTest.java
@@ -0,0 +1,77 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.openstack.swift.binders;
+
+import static org.testng.Assert.assertEquals;
+
+import java.util.List;
+
+import org.jclouds.http.HttpRequest;
+import org.jclouds.openstack.swift.CommonSwiftClientTest;
+import org.jclouds.openstack.swift.reference.SwiftHeaders;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.ImmutableList;
+
+/**
+ * Tests behavior of {@code BindIterableToHeadersWithContainerDeleteMetadataPrefix}
+ * 
+ * @author Everett Toews
+ */
+// NOTE:without testName, this will not call @Before* and fail w/NPE during surefire
+@Test(groups = "unit", testName = "BindIterableToHeadersWithContainerDeleteMetadataPrefixTest")
+public class BindIterableToHeadersWithContainerDeleteMetadataPrefixTest extends CommonSwiftClientTest {
+
+   @Test
+   public void testMetadataKeysBind() {
+      List<String> metadataKeys = ImmutableList.of("foo", "bar");
+
+      HttpRequest request = HttpRequest.builder().method("PUT").endpoint("http://localhost").build();
+      BindIterableToHeadersWithContainerDeleteMetadataPrefix binder = 
+         injector.getInstance(BindIterableToHeadersWithContainerDeleteMetadataPrefix.class);
+      
+      HttpRequest actualRequest = binder.bindToRequest(request, metadataKeys);
+      HttpRequest expectedRequest = HttpRequest.builder()
+         .method("PUT")
+         .endpoint("http://localhost")
+         .addHeader(SwiftHeaders.CONTAINER_DELETE_METADATA_PREFIX + "foo", "")
+         .addHeader(SwiftHeaders.CONTAINER_DELETE_METADATA_PREFIX + "bar", "")
+         .build(); 
+
+      assertEquals(actualRequest, expectedRequest);
+   }
+
+   @Test(expectedExceptions = NullPointerException.class)
+   public void testNullListIsBad() {
+      HttpRequest request = HttpRequest.builder().method("PUT").endpoint("http://localhost").build();
+      BindIterableToHeadersWithContainerDeleteMetadataPrefix binder = 
+         injector.getInstance(BindIterableToHeadersWithContainerDeleteMetadataPrefix.class);
+      
+      binder.bindToRequest(request, null);
+   }
+
+   @Test(expectedExceptions = NullPointerException.class)
+   public void testNullRequestIsBad() {
+      List<String> metadataKeys = ImmutableList.of("foo", "bar");
+      BindIterableToHeadersWithContainerDeleteMetadataPrefix binder = 
+         injector.getInstance(BindIterableToHeadersWithContainerDeleteMetadataPrefix.class);
+      
+      binder.bindToRequest(null, metadataKeys);
+   }
+}
diff --git a/apis/swift/src/test/java/org/jclouds/openstack/swift/binders/BindMapToHeadersWithContainerMetadataPrefixTest.java b/apis/swift/src/test/java/org/jclouds/openstack/swift/binders/BindMapToHeadersWithContainerMetadataPrefixTest.java
new file mode 100644
index 0000000..68b9c94
--- /dev/null
+++ b/apis/swift/src/test/java/org/jclouds/openstack/swift/binders/BindMapToHeadersWithContainerMetadataPrefixTest.java
@@ -0,0 +1,77 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.openstack.swift.binders;
+
+import static org.testng.Assert.assertEquals;
+
+import java.util.List;
+
+import org.jclouds.http.HttpRequest;
+import org.jclouds.openstack.swift.CommonSwiftClientTest;
+import org.jclouds.openstack.swift.reference.SwiftHeaders;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.ImmutableList;
+
+/**
+ * Tests behavior of {@code BindListToHeadersWithContainerDeleteMetadataPrefix}
+ * 
+ * @author Everett Toews
+ */
+// NOTE:without testName, this will not call @Before* and fail w/NPE during surefire
+@Test(groups = "unit", testName = "BindListToHeadersWithContainerDeleteMetadataPrefixTest")
+public class BindMapToHeadersWithContainerMetadataPrefixTest extends CommonSwiftClientTest {
+
+   @Test
+   public void testMetadataKeysBind() {
+      List<String> metadataKeys = ImmutableList.of("foo", "bar");
+
+      HttpRequest request = HttpRequest.builder().method("PUT").endpoint("http://localhost").build();
+      BindIterableToHeadersWithContainerDeleteMetadataPrefix binder = 
+         injector.getInstance(BindIterableToHeadersWithContainerDeleteMetadataPrefix.class);
+      
+      HttpRequest actualRequest = binder.bindToRequest(request, metadataKeys);
+      HttpRequest expectedRequest = HttpRequest.builder()
+         .method("PUT")
+         .endpoint("http://localhost")
+         .addHeader(SwiftHeaders.CONTAINER_DELETE_METADATA_PREFIX + "foo", "")
+         .addHeader(SwiftHeaders.CONTAINER_DELETE_METADATA_PREFIX + "bar", "")
+         .build(); 
+
+      assertEquals(actualRequest, expectedRequest);
+   }
+
+   @Test(expectedExceptions = NullPointerException.class)
+   public void testNullListIsBad() {
+      HttpRequest request = HttpRequest.builder().method("PUT").endpoint("http://localhost").build();
+      BindIterableToHeadersWithContainerDeleteMetadataPrefix binder = 
+         injector.getInstance(BindIterableToHeadersWithContainerDeleteMetadataPrefix.class);
+      
+      binder.bindToRequest(request, null);
+   }
+
+   @Test(expectedExceptions = NullPointerException.class)
+   public void testNullRequestIsBad() {
+      List<String> metadataKeys = ImmutableList.of("foo", "bar");
+      BindIterableToHeadersWithContainerDeleteMetadataPrefix binder = 
+         injector.getInstance(BindIterableToHeadersWithContainerDeleteMetadataPrefix.class);
+      
+      binder.bindToRequest(null, metadataKeys);
+   }
+}
diff --git a/apis/swift/src/test/java/org/jclouds/openstack/swift/blobstore/integration/SwiftContainerIntegrationLiveTest.java b/apis/swift/src/test/java/org/jclouds/openstack/swift/blobstore/integration/SwiftContainerIntegrationLiveTest.java
index 02e0e3d..25de625 100644
--- a/apis/swift/src/test/java/org/jclouds/openstack/swift/blobstore/integration/SwiftContainerIntegrationLiveTest.java
+++ b/apis/swift/src/test/java/org/jclouds/openstack/swift/blobstore/integration/SwiftContainerIntegrationLiveTest.java
@@ -18,15 +18,28 @@
  */
 package org.jclouds.openstack.swift.blobstore.integration;
 
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+
 import java.util.Properties;
 
+import org.jclouds.blobstore.BlobStore;
 import org.jclouds.blobstore.integration.internal.BaseContainerIntegrationTest;
 import org.jclouds.openstack.keystone.v2_0.config.KeystoneProperties;
+import org.jclouds.openstack.swift.CommonSwiftAsyncClient;
+import org.jclouds.openstack.swift.CommonSwiftClient;
+import org.jclouds.openstack.swift.domain.ContainerMetadata;
+import org.jclouds.openstack.swift.options.CreateContainerOptions;
+import org.jclouds.rest.RestContext;
 import org.testng.annotations.Test;
 
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+
 /**
  * @author James Murty
  * @author Adrian Cole
+ * @author Everett Toews
  */
 @Test(groups = "live")
 public class SwiftContainerIntegrationLiveTest extends BaseContainerIntegrationTest {
@@ -40,4 +53,53 @@
    public SwiftContainerIntegrationLiveTest() {
       provider = System.getProperty("test.swift.provider", "swift");
    }
+
+   @Test(groups = "live")
+   public void testSetGetContainerMetadata() throws InterruptedException {
+      BlobStore blobStore = view.getBlobStore();
+      RestContext<CommonSwiftClient, CommonSwiftAsyncClient> swift = blobStore.getContext().unwrap();
+      String containerName = getContainerName();
+      
+      assertTrue(swift.getApi().createContainer(containerName));
+      
+      ImmutableMap<String, String> metadata = ImmutableMap.<String, String> of(
+            "key1", "value1",
+            "key2", "value2"); 
+
+      assertTrue(swift.getApi().setContainerMetadata(containerName, metadata));
+
+      ContainerMetadata containerMetadata = swift.getApi().getContainerMetadata(containerName);
+      
+      assertEquals(containerMetadata.getMetadata().get("key1"), "value1");
+      assertEquals(containerMetadata.getMetadata().get("key2"), "value2");
+   }
+
+   @Test(groups = "live")
+   public void testCreateDeleteContainerMetadata() throws InterruptedException {
+      BlobStore blobStore = view.getBlobStore();
+      RestContext<CommonSwiftClient, CommonSwiftAsyncClient> swift = blobStore.getContext().unwrap();
+      String containerName = getContainerName();
+      CreateContainerOptions options = CreateContainerOptions.Builder
+         .withPublicAccess()
+         .withMetadata(ImmutableMap.<String, String> of(
+            "key1", "value1",
+            "key2", "value2",
+            "key3", "value3")); 
+
+      assertTrue(swift.getApi().createContainer(containerName, options));
+      
+      ContainerMetadata containerMetadata = swift.getApi().getContainerMetadata(containerName);
+      
+      assertEquals(containerMetadata.getMetadata().size(), 3);
+      assertEquals(containerMetadata.getMetadata().get("key1"), "value1");
+      assertEquals(containerMetadata.getMetadata().get("key2"), "value2");
+      assertEquals(containerMetadata.getMetadata().get("key3"), "value3");
+
+      assertTrue(swift.getApi().deleteContainerMetadata(containerName, ImmutableList.<String> of("key2","key3")));
+
+      containerMetadata = swift.getApi().getContainerMetadata(containerName);
+      
+      assertEquals(containerMetadata.getMetadata().size(), 1);
+      assertEquals(containerMetadata.getMetadata().get("key1"), "value1");
+   }
 }
diff --git a/apis/swift/src/test/java/org/jclouds/openstack/swift/blobstore/integration/SwiftContainerLiveTest.java b/apis/swift/src/test/java/org/jclouds/openstack/swift/blobstore/integration/SwiftContainerLiveTest.java
index fd7e131..e222a14 100644
--- a/apis/swift/src/test/java/org/jclouds/openstack/swift/blobstore/integration/SwiftContainerLiveTest.java
+++ b/apis/swift/src/test/java/org/jclouds/openstack/swift/blobstore/integration/SwiftContainerLiveTest.java
@@ -46,5 +46,4 @@
    public void testPublicAccess() throws MalformedURLException, InterruptedException, IOException {
       super.testPublicAccess();
    }
-
 }
diff --git a/apis/swift/src/test/java/org/jclouds/openstack/swift/functions/ParseContainerMetadataFromHeadersTest.java b/apis/swift/src/test/java/org/jclouds/openstack/swift/functions/ParseContainerMetadataFromHeadersTest.java
new file mode 100644
index 0000000..b0b4cc0
--- /dev/null
+++ b/apis/swift/src/test/java/org/jclouds/openstack/swift/functions/ParseContainerMetadataFromHeadersTest.java
@@ -0,0 +1,77 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.openstack.swift.functions;
+
+import static org.easymock.EasyMock.createMock;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.replay;
+import static org.testng.Assert.assertEquals;
+
+import java.net.URI;
+
+import org.jclouds.http.HttpResponse;
+import org.jclouds.openstack.swift.domain.ContainerMetadata;
+import org.jclouds.openstack.swift.functions.ParseContainerMetadataFromHeaders;
+import org.jclouds.openstack.swift.reference.SwiftHeaders;
+import org.jclouds.rest.internal.GeneratedHttpRequest;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.ImmutableList;
+import com.google.inject.AbstractModule;
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+
+/**
+ * Tests behavior of {@code ParseContainerMetadataFromHeaders}
+ * 
+ * @author Everett Toews
+ */
+@Test(groups = "unit")
+public class ParseContainerMetadataFromHeadersTest {
+	
+	Injector i = Guice.createInjector(new AbstractModule() {
+	
+		@Override
+		protected void configure() {
+		}	
+	});
+
+	public void testParseContainerMetadataHeaders() {
+		ParseContainerMetadataFromHeaders parser = i.getInstance(ParseContainerMetadataFromHeaders.class);
+		GeneratedHttpRequest request = createMock(GeneratedHttpRequest.class);
+		expect(request.getArgs()).andReturn(ImmutableList.<Object> of("container", "key")).atLeastOnce();
+		expect(request.getEndpoint()).andReturn(URI.create("http://localhost/test")).atLeastOnce();
+		replay(request);
+		parser.setContext(request);
+		
+		HttpResponse response = HttpResponse.builder().statusCode(204).message("No Content").payload("")
+			.addHeader(SwiftHeaders.CONTAINER_BYTES_USED, "42")
+			.addHeader(SwiftHeaders.CONTAINER_OBJECT_COUNT, "1")
+			.addHeader(SwiftHeaders.CONTAINER_METADATA_PREFIX + "label1", "test1")
+			.addHeader(SwiftHeaders.CONTAINER_METADATA_PREFIX + "label2", "test2").build();
+		
+		response.getPayload().getContentMetadata().setContentType("text/plain");
+		ContainerMetadata containerMetadata = parser.apply(response);
+		
+		assertEquals(containerMetadata.getBytes(), 42);
+		assertEquals(containerMetadata.getCount(), 1);
+		assertEquals(containerMetadata.getMetadata().get("label1"), "test1");
+		assertEquals(containerMetadata.getMetadata().get("label2"), "test2");
+	}
+}
diff --git a/apis/swift/src/test/java/org/jclouds/openstack/swift/handlers/ParseSwiftErrorFromHttpResponseTest.java b/apis/swift/src/test/java/org/jclouds/openstack/swift/handlers/ParseSwiftErrorFromHttpResponseTest.java
index bb57506..8ec2dc5 100644
--- a/apis/swift/src/test/java/org/jclouds/openstack/swift/handlers/ParseSwiftErrorFromHttpResponseTest.java
+++ b/apis/swift/src/test/java/org/jclouds/openstack/swift/handlers/ParseSwiftErrorFromHttpResponseTest.java
@@ -31,9 +31,14 @@
 import org.jclouds.blobstore.KeyNotFoundException;
 import org.jclouds.http.HttpCommand;
 import org.jclouds.http.HttpRequest;
+import org.jclouds.http.HttpRequest.Builder;
 import org.jclouds.http.HttpResponse;
+import org.jclouds.openstack.swift.CopyObjectException;
+import org.jclouds.openstack.swift.reference.SwiftHeaders;
 import org.testng.annotations.Test;
 
+import com.google.common.base.Strings;
+
 /**
  * 
  * @author Adrian Cole
@@ -42,6 +47,13 @@
 public class ParseSwiftErrorFromHttpResponseTest {
 
    @Test
+   public void test404SetsCopyObjectException() {
+      assertCodeMakes("HEAD",
+            URI.create("http://host/v1/MossoCloudFS_7064cdb1d49d4dcba3c899ac33e8409d/adriancole-blobstore1/key"), 404,
+            "Not Found", "text/plain", "", "/bad/source/path", CopyObjectException.class);
+   }
+
+   @Test
    public void test404SetsKeyNotFoundExceptionMosso() {
       assertCodeMakes("HEAD",
             URI.create("http://host/v1/MossoCloudFS_7064cdb1d49d4dcba3c899ac33e8409d/adriancole-blobstore1/key"), 404,
@@ -76,24 +88,34 @@
 
    private void assertCodeMakes(String method, URI uri, int statusCode, String message, String contentType,
          String content, Class<? extends Exception> expected) {
-
-      ParseSwiftErrorFromHttpResponse function = new ParseSwiftErrorFromHttpResponse();
-
-      HttpCommand command = createMock(HttpCommand.class);
-      HttpRequest request = HttpRequest.builder().method(method).endpoint(uri).build();
-      HttpResponse response = HttpResponse.builder().statusCode(statusCode).message(message).payload(content).build();
-      response.getPayload().getContentMetadata().setContentType(contentType);
-
-      expect(command.getCurrentRequest()).andReturn(request).atLeastOnce();
-      command.setException(classEq(expected));
-
-      replay(command);
-
-      function.handleError(command, response);
-
-      verify(command);
+      assertCodeMakes(method, uri, statusCode, message, contentType, content, "", expected);
    }
 
+   private void assertCodeMakes(String method, URI uri, int statusCode, String message, String contentType,
+	         String content, String copyObjectSourcePath, Class<? extends Exception> expected) {
+    ParseSwiftErrorFromHttpResponse function = new ParseSwiftErrorFromHttpResponse();
+
+    HttpCommand command = createMock(HttpCommand.class);
+    Builder<?> requestBuilder = HttpRequest.builder().method(method).endpoint(uri);
+    
+    if (!Strings.isNullOrEmpty(copyObjectSourcePath)) {
+      requestBuilder.addHeader(SwiftHeaders.OBJECT_COPY_FROM, copyObjectSourcePath);
+    }
+    
+    HttpRequest request = requestBuilder.build();
+    HttpResponse response = HttpResponse.builder().statusCode(statusCode).message(message).payload(content).build();
+    response.getPayload().getContentMetadata().setContentType(contentType);
+
+    expect(command.getCurrentRequest()).andReturn(request).atLeastOnce();
+    command.setException(classEq(expected));
+
+    replay(command);
+
+    function.handleError(command, response);
+
+    verify(command);	   
+ }
+
    public static Exception classEq(final Class<? extends Exception> in) {
       reportMatcher(new IArgumentMatcher() {
 
diff --git a/apis/swift/src/test/java/org/jclouds/openstack/swift/internal/StubSwiftAsyncClient.java b/apis/swift/src/test/java/org/jclouds/openstack/swift/internal/StubSwiftAsyncClient.java
index 8c11b7c..1341de2 100644
--- a/apis/swift/src/test/java/org/jclouds/openstack/swift/internal/StubSwiftAsyncClient.java
+++ b/apis/swift/src/test/java/org/jclouds/openstack/swift/internal/StubSwiftAsyncClient.java
@@ -53,6 +53,7 @@
 import org.jclouds.openstack.swift.domain.MutableObjectInfoWithMetadata;
 import org.jclouds.openstack.swift.domain.ObjectInfo;
 import org.jclouds.openstack.swift.domain.SwiftObject;
+import org.jclouds.openstack.swift.options.CreateContainerOptions;
 
 import com.google.common.base.Function;
 import com.google.common.base.Throwables;
@@ -160,12 +161,33 @@
                })));
    }
 
+   @Override
+   public ListenableFuture<ContainerMetadata> getContainerMetadata(String container) {
+      throw new UnsupportedOperationException();
+   }
+
+   public ListenableFuture<Boolean> setContainerMetadata(String container, Map<String, String> containerMetadata) {
+      throw new UnsupportedOperationException();
+   }
+
+   public ListenableFuture<Boolean> deleteContainerMetadata(String container, Iterable<String> metadataKeys) {
+      throw new UnsupportedOperationException();
+   }
+
+   public ListenableFuture<Boolean> createContainer(String container, CreateContainerOptions... options) {
+      throw new UnsupportedOperationException();
+   }
+
    public ListenableFuture<PageSet<ObjectInfo>> listObjects(String container,
             org.jclouds.openstack.swift.options.ListContainerOptions... optionsList) {
       ListContainerOptions options = container2ContainerListOptions.apply(optionsList);
       return Futures.compose(blobStore.list(container, options), resource2ObjectList, service);
    }
 
+   public ListenableFuture<Boolean> copyObject(String sourceContainer, String sourceObject, String destinationContainer, String destinationObject) {
+      throw new UnsupportedOperationException();
+   }
+
    public ListenableFuture<String> putObject(String container, SwiftObject object) {
       return blobStore.putBlob(container, object2Blob.apply(object));
    }
@@ -195,5 +217,4 @@
    public ListenableFuture<Boolean> objectExists(String bucketName, String key) {
       return blobStore.blobExists(bucketName, key);
    }
-
 }
diff --git a/apis/swift/src/test/java/org/jclouds/openstack/swift/options/CreateContainerOptionsTest.java b/apis/swift/src/test/java/org/jclouds/openstack/swift/options/CreateContainerOptionsTest.java
new file mode 100644
index 0000000..678087f
--- /dev/null
+++ b/apis/swift/src/test/java/org/jclouds/openstack/swift/options/CreateContainerOptionsTest.java
@@ -0,0 +1,71 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.openstack.swift.options;
+
+import static org.testng.Assert.assertEquals;
+
+import org.jclouds.openstack.swift.options.CreateContainerOptions;
+import org.jclouds.openstack.swift.reference.SwiftHeaders;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+
+/**
+ * Tests behavior of {@code CreateContainerOptions}
+ * 
+ * @author Adrian Cole
+ */
+@Test(groups = "unit")
+public class CreateContainerOptionsTest {
+
+   public void testPublicAccess() {
+      CreateContainerOptions options = new CreateContainerOptions().withPublicAccess();
+      assertEquals(ImmutableList.of(".r:*,.rlistings"), 
+    		       options.buildRequestHeaders().get("X-Container-Read"));
+   }
+
+   public void testPublicAccessStatic() {
+      CreateContainerOptions options = CreateContainerOptions.Builder.withPublicAccess();
+      assertEquals(ImmutableList.of(".r:*,.rlistings"), 
+    		       options.buildRequestHeaders().get("X-Container-Read"));
+   }
+
+   public void testMetadata() {
+      CreateContainerOptions options = new CreateContainerOptions().withMetadata(ImmutableMap
+               .of("test", "foo"));
+      assertEquals(ImmutableList.of("foo"), options.buildRequestHeaders().get(
+               SwiftHeaders.CONTAINER_METADATA_PREFIX + "test"));
+   }
+
+   public void testMetadataAlreadyPrefixed() {
+      CreateContainerOptions options = new CreateContainerOptions().withMetadata(ImmutableMap
+               .of(SwiftHeaders.CONTAINER_METADATA_PREFIX + "test", "foo"));
+      assertEquals(ImmutableList.of("foo"), options.buildRequestHeaders().get(
+    		  SwiftHeaders.CONTAINER_METADATA_PREFIX + "test"));
+   }
+
+   public void testMetadataStatic() {
+      CreateContainerOptions options = CreateContainerOptions.Builder
+               .withMetadata(ImmutableMap.of("test", "foo"));
+      assertEquals(ImmutableList.of("foo"), options.buildRequestHeaders().get(
+    		  SwiftHeaders.CONTAINER_METADATA_PREFIX + "test"));
+   }
+
+}
diff --git a/common/azure/src/main/java/org/jclouds/azure/storage/config/AzureStorageRestClientModule.java b/common/azure/src/main/java/org/jclouds/azure/storage/config/AzureStorageRestClientModule.java
index 86f871f..086fc7a 100644
--- a/common/azure/src/main/java/org/jclouds/azure/storage/config/AzureStorageRestClientModule.java
+++ b/common/azure/src/main/java/org/jclouds/azure/storage/config/AzureStorageRestClientModule.java
@@ -20,6 +20,7 @@
 
 import static org.jclouds.Constants.PROPERTY_SESSION_INTERVAL;
 
+import java.util.Map;
 import java.util.concurrent.TimeUnit;
 
 import javax.inject.Named;
@@ -52,6 +53,10 @@
 
    }
 
+   public AzureStorageRestClientModule(Map<Class<?>, Class<?>> delegate) {
+	      super(delegate);
+	   }
+   
    public AzureStorageRestClientModule(TypeToken<S> syncClientType, TypeToken<A> asyncClientType) {
       super(syncClientType, asyncClientType);
    }
diff --git a/common/openstack/src/main/java/org/jclouds/openstack/keystone/v1_1/config/AuthenticationServiceModule.java b/common/openstack/src/main/java/org/jclouds/openstack/keystone/v1_1/config/AuthenticationServiceModule.java
index a96f524..3cdb047 100644
--- a/common/openstack/src/main/java/org/jclouds/openstack/keystone/v1_1/config/AuthenticationServiceModule.java
+++ b/common/openstack/src/main/java/org/jclouds/openstack/keystone/v1_1/config/AuthenticationServiceModule.java
@@ -33,6 +33,7 @@
 import org.jclouds.http.HttpRetryHandler;
 import org.jclouds.http.annotation.ClientError;
 import org.jclouds.location.Provider;
+import org.jclouds.location.suppliers.ImplicitRegionIdSupplier;
 import org.jclouds.location.suppliers.RegionIdToURISupplier;
 import org.jclouds.openstack.internal.Authentication;
 import org.jclouds.openstack.keystone.v1_1.AuthenticationAsyncClient;
@@ -40,6 +41,7 @@
 import org.jclouds.openstack.keystone.v1_1.domain.Auth;
 import org.jclouds.openstack.keystone.v1_1.handlers.RetryOnRenew;
 import org.jclouds.openstack.keystone.v1_1.suppliers.RegionIdToURIFromAuthForServiceSupplier;
+import org.jclouds.openstack.keystone.v1_1.suppliers.V1DefaultRegionIdSupplier;
 
 import com.google.common.base.Function;
 import com.google.common.base.Supplier;
@@ -66,6 +68,8 @@
       bindClientAndAsyncClient(binder(), AuthenticationClient.class, AuthenticationAsyncClient.class);
       install(new FactoryModuleBuilder().implement(RegionIdToURISupplier.class,
                RegionIdToURIFromAuthForServiceSupplier.class).build(RegionIdToURISupplier.Factory.class));
+      install(new FactoryModuleBuilder().implement(ImplicitRegionIdSupplier.class, V1DefaultRegionIdSupplier.class)
+               .build(V1DefaultRegionIdSupplier.Factory.class));
       bind(HttpRetryHandler.class).annotatedWith(ClientError.class).to(RetryOnRenew.class);
    }
 
diff --git a/common/openstack/src/main/java/org/jclouds/openstack/keystone/v1_1/suppliers/RegionIdToURIFromAuthForServiceSupplier.java b/common/openstack/src/main/java/org/jclouds/openstack/keystone/v1_1/suppliers/RegionIdToURIFromAuthForServiceSupplier.java
index 2eaf742..9e05558 100644
--- a/common/openstack/src/main/java/org/jclouds/openstack/keystone/v1_1/suppliers/RegionIdToURIFromAuthForServiceSupplier.java
+++ b/common/openstack/src/main/java/org/jclouds/openstack/keystone/v1_1/suppliers/RegionIdToURIFromAuthForServiceSupplier.java
@@ -22,12 +22,11 @@
 import java.util.Collection;
 import java.util.Map;
 
-import javax.annotation.Resource;
 import javax.inject.Inject;
 import javax.inject.Singleton;
 
+import org.jclouds.javax.annotation.Nullable;
 import org.jclouds.location.suppliers.RegionIdToURISupplier;
-import org.jclouds.logging.Logger;
 import org.jclouds.openstack.keystone.v1_1.domain.Auth;
 import org.jclouds.openstack.keystone.v1_1.domain.Endpoint;
 import org.jclouds.openstack.keystone.v1_1.functions.EndpointToRegion;
@@ -39,29 +38,24 @@
 
 @Singleton
 public class RegionIdToURIFromAuthForServiceSupplier implements RegionIdToURISupplier {
-   @Resource
-   protected Logger logger = Logger.NULL;
 
    private final Supplier<Auth> auth;
    private final EndpointToSupplierURI endpointToSupplierURI;
    private final EndpointToRegion endpointToRegion;
    private final String apiType;
-   private final String apiVersion;
 
    @Inject
    public RegionIdToURIFromAuthForServiceSupplier(Supplier<Auth> auth, EndpointToSupplierURI endpointToSupplierURI,
             EndpointToRegion endpointToRegion, @Assisted("apiType") String apiType,
-            @Assisted("apiVersion") String apiVersion) {
+            @Nullable @Assisted("apiVersion") String apiVersion) {
       this.auth = auth;
       this.endpointToSupplierURI = endpointToSupplierURI;
       this.endpointToRegion = endpointToRegion;
       this.apiType = apiType;
-      this.apiVersion = apiVersion;
    }
 
    @Override
    public Map<String, Supplier<URI>> get() {
-      logger.trace("current version of keystone doesn't allow us to validate the apiVersion %s", apiVersion);
       Auth authResponse = auth.get();
       Collection<Endpoint> endpointsForService = authResponse.getServiceCatalog().get(apiType);
       Map<String, Endpoint> regionIdToEndpoint = Maps.uniqueIndex(endpointsForService, endpointToRegion);
diff --git a/common/openstack/src/main/java/org/jclouds/openstack/keystone/v1_1/suppliers/V1DefaultRegionIdSupplier.java b/common/openstack/src/main/java/org/jclouds/openstack/keystone/v1_1/suppliers/V1DefaultRegionIdSupplier.java
new file mode 100644
index 0000000..012c846
--- /dev/null
+++ b/common/openstack/src/main/java/org/jclouds/openstack/keystone/v1_1/suppliers/V1DefaultRegionIdSupplier.java
@@ -0,0 +1,87 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.openstack.keystone.v1_1.suppliers;
+
+import static com.google.common.collect.Iterables.tryFind;
+
+import java.util.NoSuchElementException;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+import org.jclouds.location.suppliers.ImplicitRegionIdSupplier;
+import org.jclouds.openstack.keystone.v1_1.domain.Auth;
+import org.jclouds.openstack.keystone.v1_1.domain.Endpoint;
+import org.jclouds.openstack.keystone.v1_1.functions.EndpointToRegion;
+
+import com.google.common.base.Optional;
+import com.google.common.base.Predicate;
+import com.google.common.base.Supplier;
+import com.google.common.collect.Iterables;
+import com.google.inject.assistedinject.Assisted;
+
+@Singleton
+public class V1DefaultRegionIdSupplier implements ImplicitRegionIdSupplier {
+
+   public static interface Factory {
+      /**
+       * 
+       * @param apiType
+       *           type of the api, according to the provider. ex. {@code compute}
+       *           {@code object-store}
+       * @return region id
+       * @throws NoSuchElementException
+       *            if the {@code apiType} is not present in the catalog
+       */
+      ImplicitRegionIdSupplier createForApiType(@Assisted("apiType") String apiType) throws NoSuchElementException;
+   }
+
+   private final Supplier<Auth> auth;
+   private final EndpointToRegion endpointToRegion;
+   private final String apiType;
+
+   @Inject
+   public V1DefaultRegionIdSupplier(Supplier<Auth> auth, EndpointToRegion endpointToRegion,
+            @Assisted("apiType") String apiType) {
+      this.auth = auth;
+      this.endpointToRegion = endpointToRegion;
+      this.apiType = apiType;
+   }
+
+   /**
+    * returns {@link Endpoint#isV1Default()} or first endpoint for service
+    */
+   @Override
+   public String get() {
+      Auth authResponse = auth.get();
+      Iterable<Endpoint> endpointsForService = authResponse.getServiceCatalog().get(apiType);
+      Optional<Endpoint> defaultEndpoint = tryFind(endpointsForService, new Predicate<Endpoint>() {
+         @Override
+         public boolean apply(Endpoint in) {
+            return in.isV1Default();
+         }
+      });
+      return endpointToRegion.apply(defaultEndpoint.or(Iterables.get(endpointsForService, 0)));
+   }
+
+   @Override
+   public String toString() {
+      return "defaultRegionIdFor(" + apiType + ")";
+   }
+}
\ No newline at end of file
diff --git a/common/openstack/src/test/java/org/jclouds/openstack/keystone/v1_1/suppliers/RegionIdToURIFromAuthForServiceSupplierTest.java b/common/openstack/src/test/java/org/jclouds/openstack/keystone/v1_1/suppliers/RegionIdToURIFromAuthForServiceSupplierTest.java
index 689a2f8..f695eb5 100644
--- a/common/openstack/src/test/java/org/jclouds/openstack/keystone/v1_1/suppliers/RegionIdToURIFromAuthForServiceSupplierTest.java
+++ b/common/openstack/src/test/java/org/jclouds/openstack/keystone/v1_1/suppliers/RegionIdToURIFromAuthForServiceSupplierTest.java
@@ -53,7 +53,6 @@
                   RegionIdToURIFromAuthForServiceSupplier.class).build(RegionIdToURISupplier.Factory.class));
       }
 
-      @SuppressWarnings("unused")
       @Provides
       @Singleton
       public Supplier<Auth> provide() {
diff --git a/common/openstack/src/test/java/org/jclouds/openstack/keystone/v1_1/suppliers/V1DefaultRegionIdSupplierTest.java b/common/openstack/src/test/java/org/jclouds/openstack/keystone/v1_1/suppliers/V1DefaultRegionIdSupplierTest.java
new file mode 100644
index 0000000..b9c2dc8
--- /dev/null
+++ b/common/openstack/src/test/java/org/jclouds/openstack/keystone/v1_1/suppliers/V1DefaultRegionIdSupplierTest.java
@@ -0,0 +1,66 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.openstack.keystone.v1_1.suppliers;
+
+import static org.testng.Assert.assertEquals;
+
+import javax.inject.Singleton;
+
+import org.jclouds.location.Provider;
+import org.jclouds.location.suppliers.ImplicitRegionIdSupplier;
+import org.jclouds.openstack.keystone.v1_1.domain.Auth;
+import org.jclouds.openstack.keystone.v1_1.parse.ParseAuthTest;
+import org.testng.annotations.Test;
+
+import com.google.common.base.Supplier;
+import com.google.common.base.Suppliers;
+import com.google.inject.AbstractModule;
+import com.google.inject.Guice;
+import com.google.inject.Provides;
+import com.google.inject.assistedinject.FactoryModuleBuilder;
+
+/**
+ * @author Adrian Cole
+ */
+@Test(groups = "unit", testName = "V1DefaultRegionIdSupplierTest")
+public class V1DefaultRegionIdSupplierTest {
+   private final V1DefaultRegionIdSupplier.Factory factory = Guice.createInjector(new AbstractModule() {
+
+      @Override
+      protected void configure() {
+         bindConstant().annotatedWith(Provider.class).to("keystone");
+         install(new FactoryModuleBuilder().implement(ImplicitRegionIdSupplier.class, V1DefaultRegionIdSupplier.class)
+                  .build(V1DefaultRegionIdSupplier.Factory.class));
+      }
+
+      @Provides
+      @Singleton
+      public Supplier<Auth> provide() {
+         return Suppliers.ofInstance(new ParseAuthTest().expected());
+      }
+   }).getInstance(V1DefaultRegionIdSupplier.Factory.class);
+
+   public void testRegionMatches() {
+      assertEquals(factory.createForApiType("cloudFilesCDN").get(), "LON");
+   }
+
+   public void testTakesFirstPartOfDNSWhenNoRegion() {
+      assertEquals(factory.createForApiType("cloudServers").get(), "lon");
+   }
+}
diff --git a/compute/src/main/java/org/jclouds/compute/domain/CIMOperatingSystem.java b/compute/src/main/java/org/jclouds/compute/domain/CIMOperatingSystem.java
index 601b673..2d46a82 100644
--- a/compute/src/main/java/org/jclouds/compute/domain/CIMOperatingSystem.java
+++ b/compute/src/main/java/org/jclouds/compute/domain/CIMOperatingSystem.java
@@ -23,6 +23,7 @@
 import org.jclouds.ovf.Envelope;
 
 import com.google.common.annotations.Beta;
+import com.google.common.base.Objects.ToStringHelper;
 
 /**
  * Operating system based on DMTF CIM model.
@@ -175,8 +176,7 @@
    }
 
    @Override
-   public String toString() {
-      return "[name=" + name + ", family=" + family + ", version=" + version + ", arch=" + arch + ", is64Bit="
-               + is64Bit + ", description=" + description + ", osType=" + osType+ "]";
+   protected ToStringHelper string() {
+      return super.string().add("osType", osType);
    }
 }
\ No newline at end of file
diff --git a/compute/src/test/java/org/jclouds/compute/JettyStatements.java b/compute/src/test/java/org/jclouds/compute/JettyStatements.java
new file mode 100644
index 0000000..1a629e5
--- /dev/null
+++ b/compute/src/test/java/org/jclouds/compute/JettyStatements.java
@@ -0,0 +1,74 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.compute;
+
+import static org.jclouds.scriptbuilder.domain.Statements.exec;
+import static org.jclouds.scriptbuilder.domain.Statements.extractTargzAndFlattenIntoDirectory;
+
+import java.net.URI;
+
+import org.jclouds.scriptbuilder.domain.Statement;
+import org.jclouds.scriptbuilder.domain.StatementList;
+import org.jclouds.scriptbuilder.statements.java.InstallJDK;
+import org.jclouds.scriptbuilder.statements.login.AdminAccess;
+
+/**
+ * 
+ * @author Adrian Cole
+ */
+public class JettyStatements {
+
+   public static final URI JETTY_URL = URI.create(System.getProperty("test.jetty-url",//
+         "http://download.eclipse.org/jetty/8.1.5.v20120716/dist/jetty-distribution-8.1.5.v20120716.tar.gz"));
+
+   public static final String JETTY_HOME = "/usr/local/jetty";
+   
+   public static final int port = 8080;
+
+   public static Statement version() {
+      return exec(String.format("head -1 %s/VERSION.txt | cut -f1 -d ' '", JETTY_HOME));
+   }
+
+   public static Statement install() {
+      return new StatementList(
+            AdminAccess.builder().adminUsername("web").build(),
+            InstallJDK.fromOpenJDK(),
+            authorizePortInIpTables(),
+            extractTargzAndFlattenIntoDirectory(JETTY_URL, JETTY_HOME),
+            exec("chown -R web " + JETTY_HOME));
+   }
+
+   private static Statement authorizePortInIpTables() {
+      return new StatementList(
+               exec("iptables -I INPUT 1 -p tcp --dport " + port + " -j ACCEPT"),
+               exec("iptables-save"));
+   }
+   
+   public static Statement start() {
+      return new StatementList(
+            exec("cd " + JETTY_HOME),
+            exec("./bin/jetty.sh start"));
+   }
+   
+   public static Statement stop() {
+      return new StatementList(
+            exec("cd " + JETTY_HOME),
+            exec("./bin/jetty.sh stop"));
+   }
+}
diff --git a/compute/src/test/java/org/jclouds/compute/RunScriptData.java b/compute/src/test/java/org/jclouds/compute/RunScriptData.java
deleted file mode 100644
index 3087d11..0000000
--- a/compute/src/test/java/org/jclouds/compute/RunScriptData.java
+++ /dev/null
@@ -1,101 +0,0 @@
-/**
- * Licensed to jclouds, Inc. (jclouds) under one or more
- * contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  jclouds licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.jclouds.compute;
-
-import static java.lang.String.format;
-import static org.jclouds.compute.util.ComputeServiceUtils.extractTargzIntoDirectory;
-import static org.jclouds.scriptbuilder.domain.Statements.appendFile;
-import static org.jclouds.scriptbuilder.domain.Statements.exec;
-import static org.jclouds.scriptbuilder.domain.Statements.interpret;
-
-import java.io.IOException;
-import java.net.URI;
-
-import org.jclouds.compute.domain.OperatingSystem;
-import org.jclouds.scriptbuilder.InitScript;
-import org.jclouds.scriptbuilder.domain.Statement;
-import org.jclouds.scriptbuilder.domain.StatementList;
-import org.jclouds.scriptbuilder.statements.java.InstallJDK;
-import org.jclouds.scriptbuilder.statements.login.AdminAccess;
-
-import com.google.common.base.Splitter;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.ImmutableList.Builder;
-
-/**
- * 
- * @author Adrian Cole
- */
-public class RunScriptData {
-
-   public static final URI JBOSS7_URL = URI.create(System.getProperty("test.jboss7-url",//
-         "http://download.jboss.org/jbossas/7.0/jboss-as-7.0.2.Final/jboss-as-web-7.0.2.Final.tar.gz"));
-
-   public static String JBOSS_HOME = "/usr/local/jboss";
-
-   public static Statement authorizePortsInIpTables(int... ports) {
-      Builder<Statement> builder = ImmutableList.builder();
-      for (int port : ports)
-         builder.add(exec("iptables -I INPUT 1 -p tcp --dport " + port + " -j ACCEPT"));
-      builder.add(exec("iptables-save"));
-      return new StatementList(builder.build());
-   }
-
-   public static StatementList installAdminUserJBossAndOpenPorts(OperatingSystem os) throws IOException {
-      return new StatementList(//
-                        AdminAccess.builder().adminUsername("web").build(),//
-                        InstallJDK.fromOpenJDK(),//
-                        authorizePortsInIpTables(22, 8080),//
-                        extractTargzIntoDirectory(JBOSS7_URL, "/usr/local"),//
-                        exec("{md} " + JBOSS_HOME), exec("mv /usr/local/jboss-*/* " + JBOSS_HOME),//
-                        changeStandaloneConfigToListenOnAllIPAddresses(),
-                        exec("chmod -R oug+r+w " + JBOSS_HOME),
-                        exec("chown -R web " + JBOSS_HOME));
-   }
-   
-   // NOTE do not name this the same as your login user, or the init process may kill you!
-   public static InitScript startJBoss(String configuration) {
-      return InitScript.builder()
-               .name("jboss")
-               .home(JBOSS_HOME)
-               .exportVariables(ImmutableMap.of("JBOSS_HOME", JBOSS_HOME))
-               .init(appendFile(JBOSS_HOME + "/standalone/configuration/standalone-custom.xml", Splitter.on('\n').split(configuration)))
-               .run(interpret(new StringBuilder().append("java ").append(' ')
-                                 .append("-server -Xms128m -Xmx128m -XX:MaxPermSize=128m -Djava.net.preferIPv4Stack=true -XX:+UseFastAccessorMethods -XX:+TieredCompilation -Xverify:none -Dorg.jboss.resolver.warning=true -Dsun.rmi.dgc.client.gcInterval=3600000 -Dsun.rmi.dgc.server.gcInterval=3600000").append(' ')
-                                 .append("-Djboss.modules.system.pkgs=org.jboss.byteman").append(' ')
-                                 .append("-Dorg.jboss.boot.log.file=$JBOSS_HOME/standalone/log/boot.log").append(' ')
-                                 .append("-Dlogging.configuration=file:$JBOSS_HOME/standalone/configuration/logging.properties").append(' ')
-                                 .append("-jar $JBOSS_HOME/jboss-modules.jar").append(' ')
-                                 .append("-mp $JBOSS_HOME/modules").append(' ')
-                                 .append("-logmodule org.jboss.logmanager").append(' ')
-                                 .append("-jaxpmodule javax.xml.jaxp-provider").append(' ')
-                                 .append("org.jboss.as.standalone").append(' ')
-                                 .append("-Djboss.home.dir=$JBOSS_HOME").append(' ')
-                                 .append("--server-config=standalone-custom.xml")
-                                 .toString())).build();
-   }
-   
-   // TODO make this a cli option
-   private static Statement changeStandaloneConfigToListenOnAllIPAddresses() {
-      return exec(format(
-                        "(cd %s/standalone/configuration && sed 's~inet-address value=.*/~any-address/~g' standalone.xml > standalone.xml.new && mv standalone.xml.new standalone.xml)",
-                        JBOSS_HOME));
-   }
-}
diff --git a/compute/src/test/java/org/jclouds/compute/StubComputeServiceIntegrationTest.java b/compute/src/test/java/org/jclouds/compute/StubComputeServiceIntegrationTest.java
index b8e71c6..32da4bb 100644
--- a/compute/src/test/java/org/jclouds/compute/StubComputeServiceIntegrationTest.java
+++ b/compute/src/test/java/org/jclouds/compute/StubComputeServiceIntegrationTest.java
@@ -36,6 +36,7 @@
 import org.jclouds.compute.domain.ExecResponse;
 import org.jclouds.compute.domain.NodeMetadata;
 import org.jclouds.compute.internal.BaseComputeServiceLiveTest;
+import org.jclouds.compute.util.OpenSocketFinder;
 import org.jclouds.crypto.Pems;
 import org.jclouds.domain.LoginCredentials;
 import org.jclouds.io.Payload;
@@ -81,12 +82,19 @@
       SocketOpen socketOpen = createMock(SocketOpen.class);
 
       expect(socketOpen.apply(HostAndPort.fromParts("144.175.1.1", 22))).andReturn(true).times(5);
-      // restart of jboss
-      expect(socketOpen.apply(HostAndPort.fromParts("144.175.1.1", 8080))).andReturn(true).times(2);
 
       replay(socketOpen);
 
-      preciseSocketTester = socketTester = new RetryablePredicate<HostAndPort>(socketOpen, 1, 1, TimeUnit.MILLISECONDS);
+      socketTester = new RetryablePredicate<HostAndPort>(socketOpen, 1, 1, TimeUnit.MILLISECONDS);
+      
+      openSocketFinder = new OpenSocketFinder(){
+
+         @Override
+         public HostAndPort findOpenSocketOnNode(NodeMetadata node, int port, long timeoutValue, TimeUnit timeUnits) {
+            return HostAndPort.fromParts("144.175.1.1", 8080);
+         }
+         
+      };
    }
 
    @Override
@@ -283,9 +291,9 @@
             client.connect();
 
             try {
-               String scriptName = "configure-jboss";
+               String scriptName = "configure-jetty";
                client.put("/tmp/init-" + scriptName, Strings2.toStringAndClose(StubComputeServiceIntegrationTest.class
-                        .getResourceAsStream("/initscript_with_jboss.sh")));
+                        .getResourceAsStream("/initscript_with_jetty.sh")));
                expect(client.exec("chmod 755 /tmp/init-" + scriptName)).andReturn(EXEC_GOOD);
                expect(client.exec("ln -fs /tmp/init-" + scriptName + " " + scriptName)).andReturn(EXEC_GOOD);
                expect(client.getUsername()).andReturn("root").atLeastOnce();
@@ -303,52 +311,27 @@
                client.disconnect();
 
                clientNew.connect();               
-               expect(clientNew.exec("ls /usr/local/jboss/bundles/org/jboss/as/osgi/configadmin/main|sed -e 's/.*-//g' -e 's/.jar//g'\n")).andReturn(EXEC_GOOD);
+               expect(clientNew.getUsername()).andReturn("web").atLeastOnce();
+               expect(clientNew.getHostAddress()).andReturn("localhost").atLeastOnce();
+               expect(clientNew.exec("head -1 /usr/local/jetty/VERSION.txt | cut -f1 -d ' '\n")).andReturn(EXEC_GOOD);
                clientNew.disconnect();
-               
-               clientNew.connect();               
-               expect(clientNew.exec("nslookup -query=a -timeout=5 download.jboss.org|grep Address|tail -1|sed 's/.* //g'\n")).andReturn(EXEC_GOOD);
-               clientNew.disconnect();
-               
-               clientNew.connect();               
-               expect(clientNew.exec("nslookup -query=a -timeout=5 download.oracle.com|grep Address|tail -1|sed 's/.* //g'\n")).andReturn(EXEC_GOOD);
-               clientNew.disconnect();
-               
-               clientNew.connect();               
-               expect(clientNew.exec("curl -q -s -S -L --connect-timeout 10 --max-time 600 --retry 20 http://checkip.amazonaws.com/\n")).andReturn(EXEC_GOOD);
-               clientNew.disconnect();
-               
+                              
                clientNew.connect();
                expect(clientNew.exec("java -fullversion\n")).andReturn(EXEC_GOOD);
                clientNew.disconnect();
 
                clientNew.connect();
-               scriptName = "jboss";
-               clientNew.put("/tmp/init-" + scriptName, Strings2
-                        .toStringAndClose(StubComputeServiceIntegrationTest.class
-                                 .getResourceAsStream("/runscript_jboss.sh")));
-               expect(clientNew.exec("chmod 755 /tmp/init-" + scriptName)).andReturn(EXEC_GOOD);
-               expect(clientNew.exec("ln -fs /tmp/init-" + scriptName + " " + scriptName)).andReturn(EXEC_GOOD);
-               expect(clientNew.getUsername()).andReturn("web").atLeastOnce();
-               expect(clientNew.getHostAddress()).andReturn("localhost").atLeastOnce();
-               expect(clientNew.exec("/tmp/init-" + scriptName + " init")).andReturn(EXEC_GOOD);
-               expect(clientNew.exec("/tmp/init-" + scriptName + " start")).andReturn(EXEC_GOOD);
-               clientNew.disconnect();
-               clientNew.connect();
-               expect(clientNew.exec("/tmp/init-" + scriptName + " stdout\n")).andReturn(EXEC_GOOD);
+               expect(clientNew.exec("cd /usr/local/jetty\n./bin/jetty.sh start\n")).andReturn(EXEC_GOOD);
                clientNew.disconnect();
 
                clientNew.connect();
-               expect(clientNew.exec("/tmp/init-" + scriptName + " stop\n")).andReturn(EXEC_GOOD);
+               expect(clientNew.exec("cd /usr/local/jetty\n./bin/jetty.sh stop\n")).andReturn(EXEC_GOOD);
                clientNew.disconnect();
 
                clientNew.connect();
-               expect(clientNew.exec("/tmp/init-" + scriptName + " start\n")).andReturn(EXEC_GOOD);
+               expect(clientNew.exec("cd /usr/local/jetty\n./bin/jetty.sh start\n")).andReturn(EXEC_GOOD);
                clientNew.disconnect();
 
-               clientNew.connect();
-               expect(clientNew.exec("/tmp/init-" + scriptName + " stdout\n")).andReturn(EXEC_GOOD);
-               clientNew.disconnect();
             } catch (IOException e) {
                Throwables.propagate(e);
             }
diff --git a/compute/src/test/java/org/jclouds/compute/internal/BaseComputeServiceLiveTest.java b/compute/src/test/java/org/jclouds/compute/internal/BaseComputeServiceLiveTest.java
index c2cecc0..7c6624a 100644
--- a/compute/src/test/java/org/jclouds/compute/internal/BaseComputeServiceLiveTest.java
+++ b/compute/src/test/java/org/jclouds/compute/internal/BaseComputeServiceLiveTest.java
@@ -31,9 +31,6 @@
 import static java.lang.String.format;
 import static java.lang.System.currentTimeMillis;
 import static java.util.logging.Logger.getAnonymousLogger;
-import static org.jclouds.compute.RunScriptData.JBOSS_HOME;
-import static org.jclouds.compute.RunScriptData.installAdminUserJBossAndOpenPorts;
-import static org.jclouds.compute.RunScriptData.startJBoss;
 import static org.jclouds.compute.options.RunScriptOptions.Builder.nameTask;
 import static org.jclouds.compute.options.RunScriptOptions.Builder.wrapInInitScript;
 import static org.jclouds.compute.options.TemplateOptions.Builder.inboundPorts;
@@ -60,17 +57,14 @@
 import java.util.concurrent.Callable;
 import java.util.concurrent.CancellationException;
 import java.util.concurrent.ExecutionException;
-import java.util.concurrent.Future;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeoutException;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
 
 import org.jclouds.compute.ComputeService;
 import org.jclouds.compute.ComputeServiceContext;
 import org.jclouds.compute.ComputeTestUtils;
+import org.jclouds.compute.JettyStatements;
 import org.jclouds.compute.RunNodesException;
-import org.jclouds.compute.RunScriptData;
 import org.jclouds.compute.RunScriptOnNodesException;
 import org.jclouds.compute.domain.ComputeMetadata;
 import org.jclouds.compute.domain.ComputeType;
@@ -83,6 +77,7 @@
 import org.jclouds.compute.domain.Template;
 import org.jclouds.compute.domain.TemplateBuilder;
 import org.jclouds.compute.options.TemplateOptions;
+import org.jclouds.compute.util.OpenSocketFinder;
 import org.jclouds.domain.Credentials;
 import org.jclouds.domain.Location;
 import org.jclouds.domain.LocationScope;
@@ -90,12 +85,12 @@
 import org.jclouds.predicates.RetryablePredicate;
 import org.jclouds.predicates.SocketOpen;
 import org.jclouds.rest.AuthorizationException;
+import org.jclouds.scriptbuilder.domain.Statement;
 import org.jclouds.scriptbuilder.domain.Statements;
 import org.jclouds.scriptbuilder.statements.java.InstallJDK;
 import org.jclouds.scriptbuilder.statements.login.AdminAccess;
 import org.jclouds.ssh.SshClient;
 import org.jclouds.ssh.SshException;
-import org.jclouds.util.Strings2;
 import org.testng.annotations.AfterClass;
 import org.testng.annotations.BeforeGroups;
 import org.testng.annotations.Test;
@@ -124,7 +119,7 @@
    protected String group;
 
    protected Predicate<HostAndPort> socketTester;
-   protected Predicate<HostAndPort> preciseSocketTester;
+   protected OpenSocketFinder openSocketFinder;
    protected SortedSet<NodeMetadata> nodes;
    protected ComputeService client;
 
@@ -159,12 +154,9 @@
       SocketOpen socketOpen = view.utils().injector().getInstance(SocketOpen.class);
       socketTester = new RetryablePredicate<HostAndPort>(socketOpen, 60, 1, TimeUnit.SECONDS);
       // wait a maximum of 60 seconds for port 8080 to open.
-      long maxWait = TimeUnit.SECONDS.toMillis(60);
-      long interval = 50;
-      // get more precise than default socket tester
-      preciseSocketTester = new RetryablePredicate<HostAndPort>(socketOpen, maxWait, interval, interval,
-            TimeUnit.MILLISECONDS);
+      openSocketFinder = context.utils().injector().getInstance(OpenSocketFinder.class);
    }
+   
    @Override
    protected void initializeContext() {
       super.initializeContext();
@@ -606,54 +598,38 @@
    static class ServiceStats {
       long backgroundProcessMilliseconds;
       long socketOpenMilliseconds;
-      long reportedStartupTimeMilliseconds;
 
       @Override
       public String toString() {
-         return String.format(
-               "[backgroundProcessMilliseconds=%s, socketOpenMilliseconds=%s, reportedStartupTimeMilliseconds=%s]",
-               backgroundProcessMilliseconds, socketOpenMilliseconds, reportedStartupTimeMilliseconds);
+         return String.format("[backgroundProcessMilliseconds=%s, socketOpenMilliseconds=%s]",
+               backgroundProcessMilliseconds, socketOpenMilliseconds);
       }
    }
 
-   protected ServiceStats trackAvailabilityOfProcessOnNode(Future<ExecResponse> bgProcess, String processName,
-         NodeMetadata node, Pattern parseReported) throws InterruptedException, ExecutionException {
+   protected ServiceStats trackAvailabilityOfProcessOnNode(Statement process, String processName, NodeMetadata node) {
       ServiceStats stats = new ServiceStats();
       Stopwatch watch = new Stopwatch().start();
-
-      ExecResponse exec = bgProcess.get();
+      ExecResponse exec = client.runScriptOnNode(node.getId(), process, runAsRoot(false).wrapInInitScript(false));
       stats.backgroundProcessMilliseconds = watch.elapsedTime(TimeUnit.MILLISECONDS);
       watch.reset().start();
+      
+      HostAndPort socket = null;
+      try {
+         socket = openSocketFinder.findOpenSocketOnNode(node, 8080, 60, TimeUnit.SECONDS);
+      } catch (NoSuchElementException e) {
+         throw new NoSuchElementException(String.format("%s%n%s%s", e.getMessage(), exec.getOutput(), exec.getError()));
+      }
 
-      HostAndPort socket = HostAndPort.fromParts(Iterables.get(node.getPublicAddresses(), 0), 8080);
-      assert preciseSocketTester.apply(socket) : String.format("failed to open socket %s on node %s:%n%s%s", socket,
-            node, init(node, processName, "stdout"), init(node, processName, "stderr"));
       stats.socketOpenMilliseconds = watch.elapsedTime(TimeUnit.MILLISECONDS);
 
-      exec = init(node, processName, "stdout");
-
-      Matcher matcher = parseReported.matcher(exec.getOutput());
-      if (matcher.find())
-         stats.reportedStartupTimeMilliseconds = Long.valueOf(matcher.group(1));
-
-      getAnonymousLogger().info(format("<< %s on node(%s) %s", bgProcess, node.getId(), stats));
+      getAnonymousLogger().info(format("<< %s on node(%s)[%s] %s", processName, node.getId(), socket, stats));
       return stats;
    }
 
-   public ExecResponse init(NodeMetadata node, String processName, String command) {
-      return client.runScriptOnNode(node.getId(), "/tmp/init-" + processName + " " + command, runAsRoot(false)
-            .wrapInInitScript(false));
-   }
-
-   // started in 6462ms -
-   public static final Pattern JBOSS_PATTERN = Pattern.compile("started in ([0-9]+)ms -");
-
    @Test(enabled = true)
    public void testCreateAndRunAService() throws Exception {
 
       String group = this.group + "s";
-      final String configuration = Strings2.toStringAndClose(RunScriptData.class
-            .getResourceAsStream("/standalone-basic.xml"));
       try {
          client.destroyNodesMatching(inGroup(group));
       } catch (Exception e) {
@@ -661,80 +637,54 @@
       }
 
       try {
-         ImmutableMap<String, String> userMetadata = ImmutableMap.<String, String> of("Name", group);
-         ImmutableSet<String> tags = ImmutableSet. of(group);
-         Stopwatch watch = new Stopwatch().start();
-         NodeMetadata node = getOnlyElement(client.createNodesInGroup(group, 1,
-               inboundPorts(22, 8080).blockOnPort(22, 300).userMetadata(userMetadata).tags(tags)));
-         long createSeconds = watch.elapsedTime(TimeUnit.SECONDS);
-
-         final String nodeId = node.getId();
-
-         checkUserMetadataInNodeEquals(node, userMetadata);
-         checkTagsInNodeEquals(node, tags);
-
-         getAnonymousLogger().info(
-               format("<< available node(%s) os(%s) in %ss", node.getId(), node.getOperatingSystem(), createSeconds));
-
-         watch.reset().start();
-
-         // note this is a dependency on the template resolution so we have the
-         // right process per
-         // operating system. moreover, we wish this to run as root, so that it
-         // can change ip
-         // tables rules and setup our admin user
-         client.runScriptOnNode(nodeId, installAdminUserJBossAndOpenPorts(node.getOperatingSystem()),
-               nameTask("configure-jboss"));
-
-         long configureSeconds = watch.elapsedTime(TimeUnit.SECONDS);
-
-         getAnonymousLogger().info(
-               format(
-                     "<< configured node(%s) with %s and JBoss %s in %ss",
-                     nodeId,
-                     exec(nodeId, "java -fullversion"),
-                     // version of the jboss jar
-                     exec(nodeId,
-                           format("ls %s/bundles/org/jboss/as/osgi/configadmin/main|sed -e 's/.*-//g' -e 's/.jar//g'",
-                                 JBOSS_HOME)), configureSeconds));
-
-         trackAvailabilityOfProcessOnNode(view.utils().userExecutor().submit(new Callable<ExecResponse>() {
-            @Override
-            public ExecResponse call() {
-               return client.runScriptOnNode(nodeId, startJBoss(configuration), runAsRoot(false).blockOnComplete(false)
-                     .nameTask("jboss"));
-            }
-
-            @Override
-            public String toString() {
-               return "initial start of jboss";
-            }
-
-         }), "jboss", node, JBOSS_PATTERN);
-
-         client.runScriptOnNode(nodeId, "/tmp/init-jboss stop", runAsRoot(false).wrapInInitScript(false));
-
-         trackAvailabilityOfProcessOnNode(view.utils().userExecutor().submit(new Callable<ExecResponse>() {
-
-            @Override
-            public ExecResponse call() {
-               return client.runScriptOnNode(nodeId, "/tmp/init-jboss start", runAsRoot(false).wrapInInitScript(false));
-            }
-
-            @Override
-            public String toString() {
-               return "warm start of jboss";
-            }
-
-         }), "jboss", node, JBOSS_PATTERN);
-
+         createAndRunAServiceInGroup(group);
       } finally {
          client.destroyNodesMatching(inGroup(group));
       }
 
    }
 
+   protected void createAndRunAServiceInGroup(String group) throws RunNodesException {
+      ImmutableMap<String, String> userMetadata = ImmutableMap.<String, String> of("Name", group);
+      ImmutableSet<String> tags = ImmutableSet. of(group);
+      Stopwatch watch = new Stopwatch().start();
+      NodeMetadata node = getOnlyElement(client.createNodesInGroup(group, 1,
+            inboundPorts(22, 8080).blockOnPort(22, 300).userMetadata(userMetadata).tags(tags)));
+      long createSeconds = watch.elapsedTime(TimeUnit.SECONDS);
+
+      final String nodeId = node.getId();
+
+      checkUserMetadataInNodeEquals(node, userMetadata);
+      checkTagsInNodeEquals(node, tags);
+
+      getAnonymousLogger().info(
+            format("<< available node(%s) os(%s) in %ss", node.getId(), node.getOperatingSystem(), createSeconds));
+
+      watch.reset().start();
+
+      client.runScriptOnNode(nodeId, JettyStatements.install(), nameTask("configure-jetty"));
+
+      long configureSeconds = watch.elapsedTime(TimeUnit.SECONDS);
+
+      getAnonymousLogger().info(
+            format(
+                  "<< configured node(%s) with %s and jetty %s in %ss",
+                  nodeId,
+                  exec(nodeId, "java -fullversion"),
+                  exec(nodeId, JettyStatements.version()), configureSeconds));
+
+      trackAvailabilityOfProcessOnNode(JettyStatements.start(), "start jetty", node);
+
+      client.runScriptOnNode(nodeId, JettyStatements.stop(), runAsRoot(false).wrapInInitScript(false));
+
+      trackAvailabilityOfProcessOnNode(JettyStatements.start(), "start jetty", node);
+   }
+
    protected String exec(final String nodeId, String command) {
+      return exec(nodeId, Statements.exec(command));
+   }
+
+   protected String exec(final String nodeId, Statement command) {
       return client.runScriptOnNode(nodeId, command, runAsRoot(false).wrapInInitScript(false)).getOutput().trim();
    }
 
diff --git a/compute/src/test/resources/.gitattributes b/compute/src/test/resources/.gitattributes
new file mode 100644
index 0000000..ba409ff
--- /dev/null
+++ b/compute/src/test/resources/.gitattributes
@@ -0,0 +1 @@
+*.sh -crlf
diff --git a/compute/src/test/resources/initscript_with_java.sh b/compute/src/test/resources/initscript_with_java.sh
index a82c905..4d60764 100644
--- a/compute/src/test/resources/initscript_with_java.sh
+++ b/compute/src/test/resources/initscript_with_java.sh
@@ -118,7 +118,7 @@
 
 # download locations for many services are at public dns
 function ensure_can_resolve_public_dns() {
-  nslookup yahoo.com > /dev/null || echo nameserver 208.67.222.222 >> /etc/resolv.conf
+  nslookup yahoo.com | grep yahoo.com > /dev/null || echo nameserver 208.67.222.222 >> /etc/resolv.conf
 }
 
 function setupPublicCurl() {
diff --git a/compute/src/test/resources/initscript_with_jboss.sh b/compute/src/test/resources/initscript_with_jboss.sh
deleted file mode 100644
index a971c4f..0000000
--- a/compute/src/test/resources/initscript_with_jboss.sh
+++ /dev/null
@@ -1,281 +0,0 @@
-#!/bin/bash
-set +u
-shopt -s xpg_echo
-shopt -s expand_aliases
-unset PATH JAVA_HOME LD_LIBRARY_PATH
-function abort {
-   echo "aborting: $@" 1>&2
-   exit 1
-}
-function default {
-   export INSTANCE_NAME="configure-jboss"
-export INSTANCE_HOME="/tmp/configure-jboss"
-export LOG_DIR="$INSTANCE_HOME"
-   return $?
-}
-function configure-jboss {
-      return $?
-}
-function findPid {
-   unset FOUND_PID;
-   [ $# -eq 1 ] || {
-      abort "findPid requires a parameter of pattern to match"
-      return 1
-   }
-   local PATTERN="$1"; shift
-   local _FOUND=`ps auxwww|grep "$PATTERN"|grep -v " $0"|grep -v grep|grep -v $$|awk '{print $2}'`
-   [ -n "$_FOUND" ] && {
-      export FOUND_PID=$_FOUND
-      return 0
-   } || {
-      return 1
-   }
-}
-function forget {
-   unset FOUND_PID;
-   [ $# -eq 3 ] || {
-      abort "forget requires parameters INSTANCE_NAME SCRIPT LOG_DIR"
-      return 1
-   }
-   local INSTANCE_NAME="$1"; shift
-   local SCRIPT="$1"; shift
-   local LOG_DIR="$1"; shift
-   mkdir -p $LOG_DIR
-   findPid $INSTANCE_NAME
-   [ -n "$FOUND_PID" -a -f $LOG_DIR/stdout.log ] && {
-      echo $INSTANCE_NAME already running pid $FOUND_PID
-      return 1;
-   } || {
-      nohup $SCRIPT >$LOG_DIR/stdout.log 2>$LOG_DIR/stderr.log &
-      RETURN=$?
-      # this is generally followed by findPid, so we shouldn't exit 
-      # immediately as the proc may not have registered in ps, yet
-      test $RETURN && sleep 1
-      return $RETURN;
-   }
-}
-export PATH=/usr/ucb/bin:/bin:/sbin:/usr/bin:/usr/sbin
-case $1 in
-init)
-   default || exit 1
-   configure-jboss || exit 1
-   mkdir -p $INSTANCE_HOME
-   
-   # create runscript header
-   cat > $INSTANCE_HOME/configure-jboss.sh <<-'END_OF_JCLOUDS_SCRIPT'
-	#!/bin/bash
-	set +u
-	shopt -s xpg_echo
-	shopt -s expand_aliases
-	
-	PROMPT_COMMAND='echo -ne \"\033]0;configure-jboss\007\"'
-	export PATH=/usr/ucb/bin:/bin:/sbin:/usr/bin:/usr/sbin
-
-	export INSTANCE_NAME='configure-jboss'
-END_OF_JCLOUDS_SCRIPT
-   cat >> $INSTANCE_HOME/configure-jboss.sh <<-END_OF_JCLOUDS_SCRIPT
-	export INSTANCE_NAME='$INSTANCE_NAME'
-	export INSTANCE_HOME='$INSTANCE_HOME'
-	export LOG_DIR='$LOG_DIR'
-END_OF_JCLOUDS_SCRIPT
-   cat >> $INSTANCE_HOME/configure-jboss.sh <<-'END_OF_JCLOUDS_SCRIPT'
-	function abort {
-   echo "aborting: $@" 1>&2
-   exit 1
-}
-alias apt-get-update="apt-get update -qq"
-alias apt-get-install="apt-get install -f -y -qq --force-yes"
-alias yum-install="yum --quiet --nogpgcheck -y install"
-
-function ensure_cmd_or_install_package_apt(){
-  local cmd=$1
-  local pkg=$2
-  
-  hash $cmd 2>/dev/null || ( apt-get-update && apt-get-install $pkg )
-}
-
-function ensure_cmd_or_install_package_yum(){
-  local cmd=$1
-  local pkg=$2
-  hash $cmd 2>/dev/null || yum-install $pkg
-}
-
-function ensure_netutils_apt() {
-  ensure_cmd_or_install_package_apt nslookup dnsutils
-  ensure_cmd_or_install_package_apt curl curl
-}
-
-function ensure_netutils_yum() {
-  ensure_cmd_or_install_package_yum nslookup bind-utils
-  ensure_cmd_or_install_package_yum curl curl
-}
-
-# most network services require that the hostname is in
-# the /etc/hosts file, or they won't operate
-function ensure_hostname_in_hosts() {
-  egrep -q `hostname` /etc/hosts || awk -v hostname=`hostname` 'END { print $1" "hostname }' /proc/net/arp >> /etc/hosts
-}
-
-# download locations for many services are at public dns
-function ensure_can_resolve_public_dns() {
-  nslookup yahoo.com > /dev/null || echo nameserver 208.67.222.222 >> /etc/resolv.conf
-}
-
-function setupPublicCurl() {
-  ensure_hostname_in_hosts
-  if which dpkg &> /dev/null; then
-    ensure_netutils_apt
-  elif which rpm &> /dev/null; then
-    ensure_netutils_yum
-  else
-    abort "we only support apt-get and yum right now... please contribute!"
-    return 1
-  fi
-  ensure_can_resolve_public_dns
-  return 0  
-}
-# adds JAVA_HOME and into PATH in global and user-specific profiles
-function setupJavaHomeInProfile() {
-  PROFILES=(/etc/bashrc $HOME/.bashrc /etc/skel/.bashrc)
-  test -n "$SUDO_USER" &&
-    PROFILES=(${PROFILES[*]} `getent passwd $SUDO_USER| cut -f6 -d:`/.bashrc)
-  for PROFILE in ${PROFILES[*]}; do
-    cat >> $PROFILE <<-'END_OF_JCLOUDS_FILE'
-	export JAVA_HOME=/usr/local/jdk
-	export PATH=$JAVA_HOME/bin:$PATH
-END_OF_JCLOUDS_FILE
-  done
-}
-
-# resets JAVA_HOME to what an openjdk installer created
-function findOpenJDK() {
-  local oldJavaHome=$JAVA_HOME
-  unset JAVA_HOME
-  for CANDIDATE in $oldJavaHome `ls -d /usr/lib/jvm/java-1.6.0-openjdk-* /usr/lib/jvm/java-6-openjdk-* /usr/lib/jvm/java-6-openjdk 2>&-`; do
-    if [ -n "$CANDIDATE" -a -x "$CANDIDATE/bin/java" ]; then
-      export JAVA_HOME=$CANDIDATE
-      break
-    fi
-  done
-}
-
-# assures JDK installed and JAVA_HOME to a link at /usr/local/jdk
-function installOpenJDK() {
-  if [ "$JAVA_HOME" == "/usr/local/jdk" ]; then
-    echo skipping as JAVA_HOME is already set to /usr/local/jdk
-    return 0
-  fi
-  if [ -n "$JAVA_HOME" -a -x "$JAVA_HOME/bin/java" ]; then
-    echo reusing JAVA_HOME $JAVA_HOME
-  else
-    if which dpkg &> /dev/null; then
-      apt-get-update && apt-get-install openjdk-6-jdk
-    elif which rpm &> /dev/null; then
-      yum-install java-1.6.0-openjdk-devel
-    else
-      abort "we only support apt-get and yum right now... please contribute"
-    fi
-    findOpenJDK
-    if [ -n "$JAVA_HOME" ]; then
-      echo installed JAVA_HOME $JAVA_HOME
-    else
-      abort "JDK installation failed"
-    fi
-  fi
-  rm -rf /usr/local/jdk
-  ln -Fs $JAVA_HOME /usr/local/jdk
-  /usr/local/jdk/bin/java -version || abort "cannot run java"
-  setupJavaHomeInProfile
-}
-
-END_OF_JCLOUDS_SCRIPT
-   
-   # add desired commands from the user
-   cat >> $INSTANCE_HOME/configure-jboss.sh <<-'END_OF_JCLOUDS_SCRIPT'
-	cd $INSTANCE_HOME
-	rm -f $INSTANCE_HOME/rc
-	trap 'echo $?>$INSTANCE_HOME/rc' 0 1 2 3 15
-	cat > /etc/sudoers <<-'END_OF_JCLOUDS_FILE'
-		root ALL = (ALL) ALL
-		%wheel ALL = (ALL) NOPASSWD:ALL
-	END_OF_JCLOUDS_FILE
-	chmod 0440 /etc/sudoers
-	mkdir -p /home/users
-	groupadd -f wheel
-	useradd -c 'web' -s /bin/bash -g wheel -m  -d /home/users/web -p 'crypt(randompassword)' web
-	mkdir -p /home/users/web/.ssh
-	cat >> /home/users/web/.ssh/authorized_keys <<-'END_OF_JCLOUDS_FILE'
-		publicKey
-	END_OF_JCLOUDS_FILE
-	chmod 600 /home/users/web/.ssh/authorized_keys
-	chown -R web /home/users/web
-	exec 3<> /etc/ssh/sshd_config && awk -v TEXT="PasswordAuthentication no
-	PermitRootLogin no
-	" 'BEGIN {print TEXT}{print}' /etc/ssh/sshd_config >&3
-	hash service 2>&- && service ssh reload 2>&- || /etc/init.d/ssh* reload
-	awk -v user=^${SUDO_USER:=${USER}}: -v password='crypt(randompassword)' 'BEGIN { FS=OFS=":" } $0 ~ user { $2 = password } 1' /etc/shadow >/etc/shadow.${SUDO_USER:=${USER}}
-	test -f /etc/shadow.${SUDO_USER:=${USER}} && mv /etc/shadow.${SUDO_USER:=${USER}} /etc/shadow
-	setupPublicCurl || return 1
-	installOpenJDK || return 1
-	iptables -I INPUT 1 -p tcp --dport 22 -j ACCEPT
-	iptables -I INPUT 1 -p tcp --dport 8080 -j ACCEPT
-	iptables-save
-	curl -q -s -S -L --connect-timeout 10 --max-time 600 --retry 20 -X GET  http://download.jboss.org/jbossas/7.0/jboss-as-7.0.2.Final/jboss-as-web-7.0.2.Final.tar.gz |(mkdir -p /usr/local &&cd /usr/local &&tar -xpzf -)
-	mkdir -p /usr/local/jboss
-	mv /usr/local/jboss-*/* /usr/local/jboss
-	(cd /usr/local/jboss/standalone/configuration && sed 's~inet-address value=.*/~any-address/~g' standalone.xml > standalone.xml.new && mv standalone.xml.new standalone.xml)
-	chmod -R oug+r+w /usr/local/jboss
-	chown -R web /usr/local/jboss
-	
-END_OF_JCLOUDS_SCRIPT
-   
-   # add runscript footer
-   cat >> $INSTANCE_HOME/configure-jboss.sh <<-'END_OF_JCLOUDS_SCRIPT'
-	exit $?
-	
-END_OF_JCLOUDS_SCRIPT
-   
-   chmod u+x $INSTANCE_HOME/configure-jboss.sh
-   ;;
-status)
-   default || exit 1
-   findPid $INSTANCE_NAME || exit 1
-   echo $FOUND_PID
-   ;;
-stop)
-   default || exit 1
-   findPid $INSTANCE_NAME || exit 1
-   [ -n "$FOUND_PID" ]  && {
-      echo stopping $FOUND_PID
-      kill -9 $FOUND_PID
-   }
-   ;;
-start)
-   default || exit 1
-   forget $INSTANCE_NAME $INSTANCE_HOME/$INSTANCE_NAME.sh $LOG_DIR || exit 1
-   ;;
-stdout)
-   default || exit 1
-   cat $LOG_DIR/stdout.log
-   ;;
-stderr)
-   default || exit 1
-   cat $LOG_DIR/stderr.log
-   ;;
-exitstatus)
-   default || exit 1
-   [ -f $LOG_DIR/rc ] && cat $LOG_DIR/rc;;
-tail)
-   default || exit 1
-   tail $LOG_DIR/stdout.log
-   ;;
-tailerr)
-   default || exit 1
-   tail $LOG_DIR/stderr.log
-   ;;
-run)
-   default || exit 1
-   $INSTANCE_HOME/$INSTANCE_NAME.sh
-   ;;
-esac
-exit $?
diff --git a/compute/src/test/resources/initscript_with_jetty.sh b/compute/src/test/resources/initscript_with_jetty.sh
new file mode 100644
index 0000000..7881e9e
--- /dev/null
+++ b/compute/src/test/resources/initscript_with_jetty.sh
@@ -0,0 +1,280 @@
+#!/bin/bash
+set +u
+shopt -s xpg_echo
+shopt -s expand_aliases
+unset PATH JAVA_HOME LD_LIBRARY_PATH
+function abort {
+   echo "aborting: $@" 1>&2
+   exit 1
+}
+function default {
+   export INSTANCE_NAME="configure-jetty"
+export INSTANCE_HOME="/tmp/configure-jetty"
+export LOG_DIR="$INSTANCE_HOME"
+   return $?
+}
+function configure-jetty {
+      return $?
+}
+function findPid {
+   unset FOUND_PID;
+   [ $# -eq 1 ] || {
+      abort "findPid requires a parameter of pattern to match"
+      return 1
+   }
+   local PATTERN="$1"; shift
+   local _FOUND=`ps auxwww|grep "$PATTERN"|grep -v " $0"|grep -v grep|grep -v $$|awk '{print $2}'`
+   [ -n "$_FOUND" ] && {
+      export FOUND_PID=$_FOUND
+      return 0
+   } || {
+      return 1
+   }
+}
+function forget {
+   unset FOUND_PID;
+   [ $# -eq 3 ] || {
+      abort "forget requires parameters INSTANCE_NAME SCRIPT LOG_DIR"
+      return 1
+   }
+   local INSTANCE_NAME="$1"; shift
+   local SCRIPT="$1"; shift
+   local LOG_DIR="$1"; shift
+   mkdir -p $LOG_DIR
+   findPid $INSTANCE_NAME
+   [ -n "$FOUND_PID" -a -f $LOG_DIR/stdout.log ] && {
+      echo $INSTANCE_NAME already running pid $FOUND_PID
+      return 1;
+   } || {
+      nohup $SCRIPT >$LOG_DIR/stdout.log 2>$LOG_DIR/stderr.log &
+      RETURN=$?
+      # this is generally followed by findPid, so we shouldn't exit 
+      # immediately as the proc may not have registered in ps, yet
+      test $RETURN && sleep 1
+      return $RETURN;
+   }
+}
+export PATH=/usr/ucb/bin:/bin:/sbin:/usr/bin:/usr/sbin
+case $1 in
+init)
+   default || exit 1
+   configure-jetty || exit 1
+   mkdir -p $INSTANCE_HOME
+   
+   # create runscript header
+   cat > $INSTANCE_HOME/configure-jetty.sh <<-'END_OF_JCLOUDS_SCRIPT'
+	#!/bin/bash
+	set +u
+	shopt -s xpg_echo
+	shopt -s expand_aliases
+	
+	PROMPT_COMMAND='echo -ne \"\033]0;configure-jetty\007\"'
+	export PATH=/usr/ucb/bin:/bin:/sbin:/usr/bin:/usr/sbin
+
+	export INSTANCE_NAME='configure-jetty'
+END_OF_JCLOUDS_SCRIPT
+   cat >> $INSTANCE_HOME/configure-jetty.sh <<-END_OF_JCLOUDS_SCRIPT
+	export INSTANCE_NAME='$INSTANCE_NAME'
+	export INSTANCE_HOME='$INSTANCE_HOME'
+	export LOG_DIR='$LOG_DIR'
+END_OF_JCLOUDS_SCRIPT
+   cat >> $INSTANCE_HOME/configure-jetty.sh <<-'END_OF_JCLOUDS_SCRIPT'
+	function abort {
+   echo "aborting: $@" 1>&2
+   exit 1
+}
+alias apt-get-update="apt-get update -qq"
+alias apt-get-install="apt-get install -f -y -qq --force-yes"
+alias yum-install="yum --quiet --nogpgcheck -y install"
+
+function ensure_cmd_or_install_package_apt(){
+  local cmd=$1
+  local pkg=$2
+  
+  hash $cmd 2>/dev/null || ( apt-get-update && apt-get-install $pkg )
+}
+
+function ensure_cmd_or_install_package_yum(){
+  local cmd=$1
+  local pkg=$2
+  hash $cmd 2>/dev/null || yum-install $pkg
+}
+
+function ensure_netutils_apt() {
+  ensure_cmd_or_install_package_apt nslookup dnsutils
+  ensure_cmd_or_install_package_apt curl curl
+}
+
+function ensure_netutils_yum() {
+  ensure_cmd_or_install_package_yum nslookup bind-utils
+  ensure_cmd_or_install_package_yum curl curl
+}
+
+# most network services require that the hostname is in
+# the /etc/hosts file, or they won't operate
+function ensure_hostname_in_hosts() {
+  egrep -q `hostname` /etc/hosts || awk -v hostname=`hostname` 'END { print $1" "hostname }' /proc/net/arp >> /etc/hosts
+}
+
+# download locations for many services are at public dns
+function ensure_can_resolve_public_dns() {
+  nslookup yahoo.com | grep yahoo.com > /dev/null || echo nameserver 208.67.222.222 >> /etc/resolv.conf
+}
+
+function setupPublicCurl() {
+  ensure_hostname_in_hosts
+  if which dpkg &> /dev/null; then
+    ensure_netutils_apt
+  elif which rpm &> /dev/null; then
+    ensure_netutils_yum
+  else
+    abort "we only support apt-get and yum right now... please contribute!"
+    return 1
+  fi
+  ensure_can_resolve_public_dns
+  return 0  
+}
+# adds JAVA_HOME and into PATH in global and user-specific profiles
+function setupJavaHomeInProfile() {
+  PROFILES=(/etc/bashrc $HOME/.bashrc /etc/skel/.bashrc)
+  test -n "$SUDO_USER" &&
+    PROFILES=(${PROFILES[*]} `getent passwd $SUDO_USER| cut -f6 -d:`/.bashrc)
+  for PROFILE in ${PROFILES[*]}; do
+    cat >> $PROFILE <<-'END_OF_JCLOUDS_FILE'
+	export JAVA_HOME=/usr/local/jdk
+	export PATH=$JAVA_HOME/bin:$PATH
+END_OF_JCLOUDS_FILE
+  done
+}
+
+# resets JAVA_HOME to what an openjdk installer created
+function findOpenJDK() {
+  local oldJavaHome=$JAVA_HOME
+  unset JAVA_HOME
+  for CANDIDATE in $oldJavaHome `ls -d /usr/lib/jvm/java-1.6.0-openjdk-* /usr/lib/jvm/java-6-openjdk-* /usr/lib/jvm/java-6-openjdk 2>&-`; do
+    if [ -n "$CANDIDATE" -a -x "$CANDIDATE/bin/java" ]; then
+      export JAVA_HOME=$CANDIDATE
+      break
+    fi
+  done
+}
+
+# assures JDK installed and JAVA_HOME to a link at /usr/local/jdk
+function installOpenJDK() {
+  if [ "$JAVA_HOME" == "/usr/local/jdk" ]; then
+    echo skipping as JAVA_HOME is already set to /usr/local/jdk
+    return 0
+  fi
+  if [ -n "$JAVA_HOME" -a -x "$JAVA_HOME/bin/java" ]; then
+    echo reusing JAVA_HOME $JAVA_HOME
+  else
+    if which dpkg &> /dev/null; then
+      apt-get-update && apt-get-install openjdk-6-jdk
+    elif which rpm &> /dev/null; then
+      yum-install java-1.6.0-openjdk-devel
+    else
+      abort "we only support apt-get and yum right now... please contribute"
+    fi
+    findOpenJDK
+    if [ -n "$JAVA_HOME" ]; then
+      echo installed JAVA_HOME $JAVA_HOME
+    else
+      abort "JDK installation failed"
+    fi
+  fi
+  rm -rf /usr/local/jdk
+  ln -Fs $JAVA_HOME /usr/local/jdk
+  /usr/local/jdk/bin/java -version || abort "cannot run java"
+  setupJavaHomeInProfile
+}
+
+END_OF_JCLOUDS_SCRIPT
+   
+   # add desired commands from the user
+   cat >> $INSTANCE_HOME/configure-jetty.sh <<-'END_OF_JCLOUDS_SCRIPT'
+	cd $INSTANCE_HOME
+	rm -f $INSTANCE_HOME/rc
+	trap 'echo $?>$INSTANCE_HOME/rc' 0 1 2 3 15
+	cat > /etc/sudoers <<-'END_OF_JCLOUDS_FILE'
+		root ALL = (ALL) ALL
+		%wheel ALL = (ALL) NOPASSWD:ALL
+	END_OF_JCLOUDS_FILE
+	chmod 0440 /etc/sudoers
+	mkdir -p /home/users
+	groupadd -f wheel
+	useradd -c 'web' -s /bin/bash -g wheel -m  -d /home/users/web -p 'crypt(randompassword)' web
+	mkdir -p /home/users/web/.ssh
+	cat >> /home/users/web/.ssh/authorized_keys <<-'END_OF_JCLOUDS_FILE'
+		publicKey
+	END_OF_JCLOUDS_FILE
+	chmod 600 /home/users/web/.ssh/authorized_keys
+	chown -R web /home/users/web
+	exec 3<> /etc/ssh/sshd_config && awk -v TEXT="PasswordAuthentication no
+	PermitRootLogin no
+	" 'BEGIN {print TEXT}{print}' /etc/ssh/sshd_config >&3
+	hash service 2>&- && service ssh reload 2>&- || /etc/init.d/ssh* reload
+	awk -v user=^${SUDO_USER:=${USER}}: -v password='crypt(randompassword)' 'BEGIN { FS=OFS=":" } $0 ~ user { $2 = password } 1' /etc/shadow >/etc/shadow.${SUDO_USER:=${USER}}
+	test -f /etc/shadow.${SUDO_USER:=${USER}} && mv /etc/shadow.${SUDO_USER:=${USER}} /etc/shadow
+	setupPublicCurl || return 1
+	installOpenJDK || return 1
+	iptables -I INPUT 1 -p tcp --dport 8080 -j ACCEPT
+	iptables-save
+	mkdir /tmp/$$
+	curl -q -s -S -L --connect-timeout 10 --max-time 600 --retry 20 -X GET  http://download.eclipse.org/jetty/8.1.5.v20120716/dist/jetty-distribution-8.1.5.v20120716.tar.gz |(mkdir -p /tmp/$$ &&cd /tmp/$$ &&tar -xpzf -)
+	mkdir -p /usr/local/jetty
+	mv /tmp/$$/*/* /usr/local/jetty
+	rm -rf /tmp/$$
+	chown -R web /usr/local/jetty
+	
+END_OF_JCLOUDS_SCRIPT
+   
+   # add runscript footer
+   cat >> $INSTANCE_HOME/configure-jetty.sh <<-'END_OF_JCLOUDS_SCRIPT'
+	exit $?
+	
+END_OF_JCLOUDS_SCRIPT
+   
+   chmod u+x $INSTANCE_HOME/configure-jetty.sh
+   ;;
+status)
+   default || exit 1
+   findPid $INSTANCE_NAME || exit 1
+   echo $FOUND_PID
+   ;;
+stop)
+   default || exit 1
+   findPid $INSTANCE_NAME || exit 1
+   [ -n "$FOUND_PID" ]  && {
+      echo stopping $FOUND_PID
+      kill -9 $FOUND_PID
+   }
+   ;;
+start)
+   default || exit 1
+   forget $INSTANCE_NAME $INSTANCE_HOME/$INSTANCE_NAME.sh $LOG_DIR || exit 1
+   ;;
+stdout)
+   default || exit 1
+   cat $LOG_DIR/stdout.log
+   ;;
+stderr)
+   default || exit 1
+   cat $LOG_DIR/stderr.log
+   ;;
+exitstatus)
+   default || exit 1
+   [ -f $LOG_DIR/rc ] && cat $LOG_DIR/rc;;
+tail)
+   default || exit 1
+   tail $LOG_DIR/stdout.log
+   ;;
+tailerr)
+   default || exit 1
+   tail $LOG_DIR/stderr.log
+   ;;
+run)
+   default || exit 1
+   $INSTANCE_HOME/$INSTANCE_NAME.sh
+   ;;
+esac
+exit $?
diff --git a/compute/src/test/resources/runscript.sh b/compute/src/test/resources/runscript.sh
index 984caa7..52f622d 100644
--- a/compute/src/test/resources/runscript.sh
+++ b/compute/src/test/resources/runscript.sh
@@ -118,7 +118,7 @@
 
 # download locations for many services are at public dns
 function ensure_can_resolve_public_dns() {
-  nslookup yahoo.com > /dev/null || echo nameserver 208.67.222.222 >> /etc/resolv.conf
+  nslookup yahoo.com | grep yahoo.com > /dev/null || echo nameserver 208.67.222.222 >> /etc/resolv.conf
 }
 
 function setupPublicCurl() {
diff --git a/compute/src/test/resources/runscript_jboss.sh b/compute/src/test/resources/runscript_jboss.sh
deleted file mode 100644
index 172cb9e..0000000
--- a/compute/src/test/resources/runscript_jboss.sh
+++ /dev/null
@@ -1,247 +0,0 @@
-#!/bin/bash
-set +u
-shopt -s xpg_echo
-shopt -s expand_aliases
-unset PATH JAVA_HOME LD_LIBRARY_PATH
-function abort {
-   echo "aborting: $@" 1>&2
-   exit 1
-}
-function default {
-   export INSTANCE_NAME="jboss"
-export INSTANCE_HOME="/usr/local/jboss"
-export LOG_DIR="$INSTANCE_HOME"
-   return $?
-}
-function jboss {
-   export JBOSS_HOME="/usr/local/jboss"
-   return $?
-}
-function findPid {
-   unset FOUND_PID;
-   [ $# -eq 1 ] || {
-      abort "findPid requires a parameter of pattern to match"
-      return 1
-   }
-   local PATTERN="$1"; shift
-   local _FOUND=`ps auxwww|grep "$PATTERN"|grep -v " $0"|grep -v grep|grep -v $$|awk '{print $2}'`
-   [ -n "$_FOUND" ] && {
-      export FOUND_PID=$_FOUND
-      return 0
-   } || {
-      return 1
-   }
-}
-function forget {
-   unset FOUND_PID;
-   [ $# -eq 3 ] || {
-      abort "forget requires parameters INSTANCE_NAME SCRIPT LOG_DIR"
-      return 1
-   }
-   local INSTANCE_NAME="$1"; shift
-   local SCRIPT="$1"; shift
-   local LOG_DIR="$1"; shift
-   mkdir -p $LOG_DIR
-   findPid $INSTANCE_NAME
-   [ -n "$FOUND_PID" -a -f $LOG_DIR/stdout.log ] && {
-      echo $INSTANCE_NAME already running pid $FOUND_PID
-      return 1;
-   } || {
-      nohup $SCRIPT >$LOG_DIR/stdout.log 2>$LOG_DIR/stderr.log &
-      RETURN=$?
-      # this is generally followed by findPid, so we shouldn't exit 
-      # immediately as the proc may not have registered in ps, yet
-      test $RETURN && sleep 1
-      return $RETURN;
-   }
-}
-export PATH=/usr/ucb/bin:/bin:/sbin:/usr/bin:/usr/sbin
-case $1 in
-init)
-   default || exit 1
-   jboss || exit 1
-   cat >> /usr/local/jboss/standalone/configuration/standalone-custom.xml <<-'END_OF_JCLOUDS_FILE'
-	<?xml version='1.0' encoding='UTF-8'?>
-	
-	<server name="basic" xmlns="urn:jboss:domain:1.0">
-	    <extensions>
-	        <extension module="org.jboss.as.connector"/>
-	        <extension module="org.jboss.as.deployment-scanner"/>
-	        <extension module="org.jboss.as.ee"/>
-	        <extension module="org.jboss.as.logging"/>
-	        <extension module="org.jboss.as.naming"/>
-	        <extension module="org.jboss.as.security"/>
-	        <extension module="org.jboss.as.threads"/>
-	        <extension module="org.jboss.as.transactions"/>
-	        <extension module="org.jboss.as.web"/>
-	        <!--
-	        <extension module="org.jboss.as.weld"/>
-	        -->
-	    </extensions>
-	    <profile>
-	        <subsystem xmlns="urn:jboss:domain:logging:1.0">
-	            <console-handler name="CONSOLE" autoflush="true">
-	                <level name="INFO"/>
-	                <formatter>
-	                    <pattern-formatter pattern="%d{HH:mm:ss,SSS} %-5p [%c] (%t) %s%E%n"/>
-	                </formatter>
-	            </console-handler>
-	            <periodic-rotating-file-handler name="FILE" autoflush="true">
-	                <level name="INFO"/>
-	                <formatter>
-	                    <pattern-formatter pattern="%d{HH:mm:ss,SSS} %-5p [%c] (%t) %s%E%n"/>
-	                </formatter>
-	                <file relative-to="jboss.server.log.dir" path="server.log"/>
-	                <suffix value=".yyyy-MM-dd"/>
-	            </periodic-rotating-file-handler>
-	            <logger category="com.arjuna">
-	                <level name="WARN"/>
-	            </logger>
-	            <logger category="org.apache.tomcat.util.modeler">
-	                <level name="WARN"/>
-	            </logger>
-	            <logger category="sun.rmi">
-	                <level name="WARN"/>
-	            </logger>
-	            <root-logger>
-	                <level name="INFO"/>
-	                <handlers>
-	                    <handler name="CONSOLE"/>
-	                    <handler name="FILE"/>
-	                </handlers>
-	            </root-logger>
-	        </subsystem>
-	        <subsystem xmlns="urn:jboss:domain:deployment-scanner:1.0">
-	            <deployment-scanner name="default" path="deployments" scan-enabled="true" scan-interval="5000" relative-to="jboss.server.base.dir" deployment-timeout="60"/>
-	        </subsystem>
-	        <subsystem xmlns="urn:jboss:domain:ee:1.0"/>
-	        <subsystem xmlns="urn:jboss:domain:naming:1.0"/>
-	        <subsystem xmlns="urn:jboss:domain:resource-adapters:1.0"/>
-	        <subsystem xmlns="urn:jboss:domain:security:1.0">
-	            <security-domains>
-	                <security-domain name="other" cache-type="default">
-	                    <authentication>
-	                        <login-module code="UsersRoles" flag="required"/>
-	                    </authentication>
-	                </security-domain>
-	            </security-domains>
-	        </subsystem>
-	        <subsystem xmlns="urn:jboss:domain:threads:1.0"/>
-	        <subsystem xmlns="urn:jboss:domain:transactions:1.0">
-	            <core-environment>
-	                <process-id>
-	                    <uuid/>
-	                </process-id>
-	            </core-environment>
-	            <recovery-environment socket-binding="txn-recovery-environment" status-socket-binding="txn-status-manager"/>
-	            <coordinator-environment default-timeout="300"/>
-	            <object-store/>
-	        </subsystem>
-	        <subsystem xmlns="urn:jboss:domain:web:1.0">
-	            <connector name="http" protocol="HTTP/1.1" socket-binding="http" scheme="http"/>
-	            <virtual-server name="localhost" enable-welcome-root="true">
-	                <alias name="example.com"/>
-	            </virtual-server>
-	        </subsystem>
-	        <!--
-	        <subsystem xmlns="urn:jboss:domain:weld:1.0"/>
-	        -->
-	    </profile>
-	    <interfaces>
-	        <interface name="public">
-	            <any-address/>
-	        </interface>
-	    </interfaces>
-	    <socket-binding-group name="standard-sockets" default-interface="public">
-	        <socket-binding name="http" port="8080"/>
-	        <socket-binding name="https" port="8443"/>
-	        <socket-binding name="jmx-connector-registry" port="1090"/>
-	        <socket-binding name="jmx-connector-server" port="1091"/>
-	        <socket-binding name="jndi" port="1099"/>
-	        <socket-binding name="osgi-http" port="8090"/>
-	        <socket-binding name="remoting" port="4447"/>
-	        <socket-binding name="txn-recovery-environment" port="4712"/>
-	        <socket-binding name="txn-status-manager" port="4713"/>
-	    </socket-binding-group>
-	</server>
-	
-END_OF_JCLOUDS_FILE
-   mkdir -p $INSTANCE_HOME
-   
-   # create runscript header
-   cat > $INSTANCE_HOME/jboss.sh <<-'END_OF_JCLOUDS_SCRIPT'
-	#!/bin/bash
-	set +u
-	shopt -s xpg_echo
-	shopt -s expand_aliases
-	
-	PROMPT_COMMAND='echo -ne \"\033]0;jboss\007\"'
-	export PATH=/usr/ucb/bin:/bin:/sbin:/usr/bin:/usr/sbin
-
-	export INSTANCE_NAME='jboss'
-END_OF_JCLOUDS_SCRIPT
-   cat >> $INSTANCE_HOME/jboss.sh <<-END_OF_JCLOUDS_SCRIPT
-	export JBOSS_HOME='$JBOSS_HOME'
-	export INSTANCE_NAME='$INSTANCE_NAME'
-	export INSTANCE_HOME='$INSTANCE_HOME'
-	export LOG_DIR='$LOG_DIR'
-END_OF_JCLOUDS_SCRIPT
-   
-   # add desired commands from the user
-   cat >> $INSTANCE_HOME/jboss.sh <<-'END_OF_JCLOUDS_SCRIPT'
-	cd $INSTANCE_HOME
-	rm -f $INSTANCE_HOME/rc
-	trap 'echo $?>$INSTANCE_HOME/rc' 0 1 2 3 15
-	java  -server -Xms128m -Xmx128m -XX:MaxPermSize=128m -Djava.net.preferIPv4Stack=true -XX:+UseFastAccessorMethods -XX:+TieredCompilation -Xverify:none -Dorg.jboss.resolver.warning=true -Dsun.rmi.dgc.client.gcInterval=3600000 -Dsun.rmi.dgc.server.gcInterval=3600000 -Djboss.modules.system.pkgs=org.jboss.byteman -Dorg.jboss.boot.log.file=$JBOSS_HOME/standalone/log/boot.log -Dlogging.configuration=file:$JBOSS_HOME/standalone/configuration/logging.properties -jar $JBOSS_HOME/jboss-modules.jar -mp $JBOSS_HOME/modules -logmodule org.jboss.logmanager -jaxpmodule javax.xml.jaxp-provider org.jboss.as.standalone -Djboss.home.dir=$JBOSS_HOME --server-config=standalone-custom.xml
-END_OF_JCLOUDS_SCRIPT
-   
-   # add runscript footer
-   cat >> $INSTANCE_HOME/jboss.sh <<-'END_OF_JCLOUDS_SCRIPT'
-	exit $?
-	
-END_OF_JCLOUDS_SCRIPT
-   
-   chmod u+x $INSTANCE_HOME/jboss.sh
-   ;;
-status)
-   default || exit 1
-   findPid $INSTANCE_NAME || exit 1
-   echo $FOUND_PID
-   ;;
-stop)
-   default || exit 1
-   findPid $INSTANCE_NAME || exit 1
-   [ -n "$FOUND_PID" ]  && {
-      echo stopping $FOUND_PID
-      kill -9 $FOUND_PID
-   }
-   ;;
-start)
-   default || exit 1
-   forget $INSTANCE_NAME $INSTANCE_HOME/$INSTANCE_NAME.sh $LOG_DIR || exit 1
-   ;;
-stdout)
-   default || exit 1
-   cat $LOG_DIR/stdout.log
-   ;;
-stderr)
-   default || exit 1
-   cat $LOG_DIR/stderr.log
-   ;;
-exitstatus)
-   default || exit 1
-   [ -f $LOG_DIR/rc ] && cat $LOG_DIR/rc;;
-tail)
-   default || exit 1
-   tail $LOG_DIR/stdout.log
-   ;;
-tailerr)
-   default || exit 1
-   tail $LOG_DIR/stderr.log
-   ;;
-run)
-   default || exit 1
-   $INSTANCE_HOME/$INSTANCE_NAME.sh
-   ;;
-esac
-exit $?
diff --git a/compute/src/test/resources/standalone-basic.xml b/compute/src/test/resources/standalone-basic.xml
deleted file mode 100644
index 5a96749..0000000
--- a/compute/src/test/resources/standalone-basic.xml
+++ /dev/null
@@ -1,103 +0,0 @@
-<?xml version='1.0' encoding='UTF-8'?>
-
-<server name="basic" xmlns="urn:jboss:domain:1.0">
-    <extensions>
-        <extension module="org.jboss.as.connector"/>
-        <extension module="org.jboss.as.deployment-scanner"/>
-        <extension module="org.jboss.as.ee"/>
-        <extension module="org.jboss.as.logging"/>
-        <extension module="org.jboss.as.naming"/>
-        <extension module="org.jboss.as.security"/>
-        <extension module="org.jboss.as.threads"/>
-        <extension module="org.jboss.as.transactions"/>
-        <extension module="org.jboss.as.web"/>
-        <!--
-        <extension module="org.jboss.as.weld"/>
-        -->
-    </extensions>
-    <profile>
-        <subsystem xmlns="urn:jboss:domain:logging:1.0">
-            <console-handler name="CONSOLE" autoflush="true">
-                <level name="INFO"/>
-                <formatter>
-                    <pattern-formatter pattern="%d{HH:mm:ss,SSS} %-5p [%c] (%t) %s%E%n"/>
-                </formatter>
-            </console-handler>
-            <periodic-rotating-file-handler name="FILE" autoflush="true">
-                <level name="INFO"/>
-                <formatter>
-                    <pattern-formatter pattern="%d{HH:mm:ss,SSS} %-5p [%c] (%t) %s%E%n"/>
-                </formatter>
-                <file relative-to="jboss.server.log.dir" path="server.log"/>
-                <suffix value=".yyyy-MM-dd"/>
-            </periodic-rotating-file-handler>
-            <logger category="com.arjuna">
-                <level name="WARN"/>
-            </logger>
-            <logger category="org.apache.tomcat.util.modeler">
-                <level name="WARN"/>
-            </logger>
-            <logger category="sun.rmi">
-                <level name="WARN"/>
-            </logger>
-            <root-logger>
-                <level name="INFO"/>
-                <handlers>
-                    <handler name="CONSOLE"/>
-                    <handler name="FILE"/>
-                </handlers>
-            </root-logger>
-        </subsystem>
-        <subsystem xmlns="urn:jboss:domain:deployment-scanner:1.0">
-            <deployment-scanner name="default" path="deployments" scan-enabled="true" scan-interval="5000" relative-to="jboss.server.base.dir" deployment-timeout="60"/>
-        </subsystem>
-        <subsystem xmlns="urn:jboss:domain:ee:1.0"/>
-        <subsystem xmlns="urn:jboss:domain:naming:1.0"/>
-        <subsystem xmlns="urn:jboss:domain:resource-adapters:1.0"/>
-        <subsystem xmlns="urn:jboss:domain:security:1.0">
-            <security-domains>
-                <security-domain name="other" cache-type="default">
-                    <authentication>
-                        <login-module code="UsersRoles" flag="required"/>
-                    </authentication>
-                </security-domain>
-            </security-domains>
-        </subsystem>
-        <subsystem xmlns="urn:jboss:domain:threads:1.0"/>
-        <subsystem xmlns="urn:jboss:domain:transactions:1.0">
-            <core-environment>
-                <process-id>
-                    <uuid/>
-                </process-id>
-            </core-environment>
-            <recovery-environment socket-binding="txn-recovery-environment" status-socket-binding="txn-status-manager"/>
-            <coordinator-environment default-timeout="300"/>
-            <object-store/>
-        </subsystem>
-        <subsystem xmlns="urn:jboss:domain:web:1.0">
-            <connector name="http" protocol="HTTP/1.1" socket-binding="http" scheme="http"/>
-            <virtual-server name="localhost" enable-welcome-root="true">
-                <alias name="example.com"/>
-            </virtual-server>
-        </subsystem>
-        <!--
-        <subsystem xmlns="urn:jboss:domain:weld:1.0"/>
-        -->
-    </profile>
-    <interfaces>
-        <interface name="public">
-            <any-address/>
-        </interface>
-    </interfaces>
-    <socket-binding-group name="standard-sockets" default-interface="public">
-        <socket-binding name="http" port="8080"/>
-        <socket-binding name="https" port="8443"/>
-        <socket-binding name="jmx-connector-registry" port="1090"/>
-        <socket-binding name="jmx-connector-server" port="1091"/>
-        <socket-binding name="jndi" port="1099"/>
-        <socket-binding name="osgi-http" port="8090"/>
-        <socket-binding name="remoting" port="4447"/>
-        <socket-binding name="txn-recovery-environment" port="4712"/>
-        <socket-binding name="txn-status-manager" port="4713"/>
-    </socket-binding-group>
-</server>
diff --git a/core/src/main/java/org/jclouds/osgi/MetadataBundleListener.java b/core/src/main/java/org/jclouds/osgi/MetadataBundleListener.java
index 5ce59c5..07cbf58 100644
--- a/core/src/main/java/org/jclouds/osgi/MetadataBundleListener.java
+++ b/core/src/main/java/org/jclouds/osgi/MetadataBundleListener.java
@@ -91,7 +91,7 @@
         providerMetadata = providerMetadataMap.get(event.getBundle().getBundleId());
         apiMetadata = apiMetadataMap.get(event.getBundle().getBundleId());
         if (providerMetadata != null) {
-          ProviderRegistry.uRegisterProvider(providerMetadata);
+          ProviderRegistry.unregisterProvider(providerMetadata);
         }
         if (apiMetadata != null) {
           ApiRegistry.unRegisterApi(apiMetadata);
diff --git a/core/src/main/java/org/jclouds/providers/ProviderRegistry.java b/core/src/main/java/org/jclouds/providers/ProviderRegistry.java
index ef96bf3..b79741e 100644
--- a/core/src/main/java/org/jclouds/providers/ProviderRegistry.java
+++ b/core/src/main/java/org/jclouds/providers/ProviderRegistry.java
@@ -32,7 +32,7 @@
     providers.add(provider);
   }
 
-  public static void uRegisterProvider(ProviderMetadata provider) {
+  public static void unregisterProvider(ProviderMetadata provider) {
     providers.remove(provider);
   }
 
diff --git a/core/src/main/java/org/jclouds/util/Suppliers2.java b/core/src/main/java/org/jclouds/util/Suppliers2.java
index 0d02f6b..21783e4 100644
--- a/core/src/main/java/org/jclouds/util/Suppliers2.java
+++ b/core/src/main/java/org/jclouds/util/Suppliers2.java
@@ -41,20 +41,39 @@
  */
 public class Suppliers2 {
 
-   public static <K, V> Supplier<V> getLastValueInMap(Supplier<Map<K, Supplier<V>>> input) {
-      return Suppliers2.compose(new Function<Map<K, Supplier<V>>, V>() {
+   /**
+    * Supplies a value that corresponds to a particular key in a map, or null, if not found
+    */
+   public static <K, V> Supplier<V> valueForKey(final Supplier<Map<K, Supplier<V>>> input, final Supplier<K> key) {
+      return new Supplier<V>() {
 
          @Override
-         public V apply(Map<K, Supplier<V>> input) {
-            Supplier<V> last = Iterables.getLast(input.values());
-            return last.get();
+         public V get() {
+            K keyToFind = key.get();
+            Supplier<V> value = input.get().get(keyToFind);
+            return value != null ? value.get() : null;
+         }
+
+         @Override
+         public String toString() {
+            return "withKey()";
+         }
+      };
+   }
+
+   public static <K, V> Supplier<V> getLastValueInMap(final Supplier<Map<K, Supplier<V>>> input) {
+      return new Supplier<V>() {
+         @Override
+         public V get() {
+            Supplier<V> last = Iterables.getLast(input.get().values());
+            return last != null ? last.get() : null;
          }
 
          @Override
          public String toString() {
             return "getLastValueInMap()";
          }
-      }, input);
+      };
    }
 
    public static <X> Function<X, Supplier<X>> ofInstanceFunction() {
diff --git a/core/src/test/java/org/jclouds/util/Suppliers2Test.java b/core/src/test/java/org/jclouds/util/Suppliers2Test.java
index 612bd5f..dc95400 100644
--- a/core/src/test/java/org/jclouds/util/Suppliers2Test.java
+++ b/core/src/test/java/org/jclouds/util/Suppliers2Test.java
@@ -32,6 +32,22 @@
 public class Suppliers2Test {
 
    @Test
+   public void testWithKey() {
+      assertEquals(
+               Suppliers2.<String, String> valueForKey(
+                        Suppliers.<Map<String, Supplier<String>>> ofInstance(ImmutableMap.of("foo",
+                                 Suppliers.ofInstance("bar"))), Suppliers.ofInstance("foo")).get(), "bar");
+   }
+   
+   @Test
+   public void testWithKeyUnmatchedIsNull() {
+      assertEquals(
+               Suppliers2.<String, String> valueForKey(
+                        Suppliers.<Map<String, Supplier<String>>> ofInstance(ImmutableMap.of("boo",
+                                 Suppliers.ofInstance("bar"))), Suppliers.ofInstance("foo")).get(), null);
+   }
+   
+   @Test
    public void testGetLastValueInMap() {
       assertEquals(
                Suppliers2.<String, String> getLastValueInMap(
diff --git a/labs/azure-management/.gitignore b/labs/azure-management/.gitignore
new file mode 100644
index 0000000..83c270e
--- /dev/null
+++ b/labs/azure-management/.gitignore
@@ -0,0 +1,9 @@
+# use glob syntax.
+syntax: glob
+target
+.settings
+.classpath
+.project
+jclouds-azure-management.iml
+jclouds-azure-management.ipr
+jclouds-azure-management.iws
diff --git a/labs/azure-management/README.txt b/labs/azure-management/README.txt
new file mode 100644
index 0000000..4136495
--- /dev/null
+++ b/labs/azure-management/README.txt
@@ -0,0 +1,8 @@
+ How to create the certificate :
+ 
+ Create the .cer and pfx files using http://www.windowsazure4j.org/learn/labs/Management/index.html or http://msdn.microsoft.com/en-us/library/gg551722
+  
+ Add it to azure : http://msdn.microsoft.com/en-us/library/gg551726
+  
+ Generate the keystore  http://stackoverflow.com/questions/4217107/how-to-convert-pfx-file-to-keystore-with-private-key
+   openssl pkcs12 -in certificate.pfx -out certificate.pem
diff --git a/labs/azure-management/pom.xml b/labs/azure-management/pom.xml
new file mode 100644
index 0000000..abfeb16
--- /dev/null
+++ b/labs/azure-management/pom.xml
@@ -0,0 +1,130 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+  Licensed to jclouds, Inc. (jclouds) under one or more
+  contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  jclouds licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing,
+  software distributed under the License is distributed on an
+  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  KIND, either express or implied.  See the License for the
+  specific language governing permissions and limitations
+  under the License.
+
+-->
+<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.5.0-SNAPSHOT</version>
+    <relativePath>../../project/pom.xml</relativePath>
+  </parent>
+  <groupId>org.jclouds.labs</groupId>
+  <artifactId>azure-management</artifactId>
+  <name>jcloud azure-management api</name>
+  <description>jclouds components to access an implementation of Azure Management</description>
+  <packaging>bundle</packaging>
+
+  <properties>
+    <test.jclouds.azure.management.subscription-id>FIXME_subscription-id</test.jclouds.azure.management.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.azure-management.endpoint>https://management.core.windows.net/${jclouds.azure.management.subscription-id}</test.azure-management.endpoint>
+    <test.azure-management.api-version>2012-03-01</test.azure-management.api-version>
+    <test.azure-management.build-version></test.azure-management.build-version>
+    <test.azure-management.identity>/path/to/cert.p12</test.azure-management.identity>
+    <test.azure-management.credential>password to cert</test.azure-management.credential>
+    <jclouds.osgi.export>org.jclouds.azure.management*;version="${project.version}"</jclouds.osgi.export>
+    <jclouds.osgi.import>
+      org.jclouds.rest.internal;version="${project.version}",
+      org.jclouds*;version="${project.version}",
+      *
+    </jclouds.osgi.import>
+  </properties>
+
+  <dependencies>
+    <dependency>
+      <groupId>com.jamesmurty.utils</groupId>
+      <artifactId>java-xmlbuilder</artifactId>
+      <version>0.4</version>
+    </dependency>
+    <dependency>
+      <groupId>org.jclouds</groupId>
+      <artifactId>jclouds-compute</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.jclouds</groupId>
+      <artifactId>jclouds-compute</artifactId>
+      <version>${project.version}</version>
+      <type>test-jar</type>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.jclouds</groupId>
+      <artifactId>jclouds-core</artifactId>
+      <version>${project.version}</version>
+      <type>test-jar</type>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.jclouds.driver</groupId>
+      <artifactId>jclouds-slf4j</artifactId>
+      <version>${project.version}</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.jclouds.driver</groupId>
+      <artifactId>jclouds-sshj</artifactId>
+      <version>${project.version}</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>ch.qos.logback</groupId>
+      <artifactId>logback-classic</artifactId>
+      <version>1.0.0</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>
+                  <systemPropertyVariables>
+                    <test.azure-management.endpoint>${test.azure-management.endpoint}</test.azure-management.endpoint>
+                    <test.azure-management.api-version>${test.azure-management.api-version}</test.azure-management.api-version>
+                    <test.azure-management.build-version>${test.azure-management.build-version}</test.azure-management.build-version>
+                    <test.azure-management.identity>${test.azure-management.identity}</test.azure-management.identity>
+                    <test.azure-management.credential>${test.azure-management.credential}</test.azure-management.credential>
+                    <test.jclouds.azure.management.subscription-id>${test.jclouds.azure.management.subscription-id}</test.jclouds.azure.management.subscription-id>
+                  </systemPropertyVariables>
+                </configuration>
+              </execution>
+            </executions>
+          </plugin>
+        </plugins>
+      </build>
+    </profile>
+  </profiles>
+
+</project>
diff --git a/labs/azure-management/src/main/java/org/jclouds/azure/management/AzureManagementApi.java b/labs/azure-management/src/main/java/org/jclouds/azure/management/AzureManagementApi.java
new file mode 100644
index 0000000..72c49ea
--- /dev/null
+++ b/labs/azure-management/src/main/java/org/jclouds/azure/management/AzureManagementApi.java
@@ -0,0 +1,100 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.azure.management;
+
+import java.util.concurrent.TimeUnit;
+
+import org.jclouds.azure.management.features.DiskApi;
+import org.jclouds.azure.management.features.HostedServiceApi;
+import org.jclouds.azure.management.features.LocationApi;
+import org.jclouds.azure.management.features.OSImageApi;
+import org.jclouds.azure.management.features.OperationApi;
+import org.jclouds.azure.management.features.RoleApi;
+import org.jclouds.concurrent.Timeout;
+import org.jclouds.rest.annotations.Delegate;
+
+/**
+ * The Windows Azure Service Management API is a REST API for managing your services and
+ * deployments.
+ * <p/>
+ * 
+ * @see AzureManagementAsyncApi
+ * @see <a href="http://msdn.microsoft.com/en-us/library/ee460799" >doc</a>
+ * @author Gerald Pereira, Adrian Cole
+ */
+@Timeout(duration = 4, timeUnit = TimeUnit.SECONDS)
+public interface AzureManagementApi {
+   /**
+    * 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>
+    * @see AzureManagementAsyncApi#getLocationApi()
+    */
+   @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>
+    * @see AzureManagementAsyncApi#getHostedServiceApi()
+    */
+   @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>
+    * @see AzureManagementAsyncApi#getRoleApi()
+    */
+   @Delegate
+   RoleApi getRoleApi();
+
+   /**
+    * 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>
+    * @see AzureManagementAsyncApi#getOSImageApi()
+    */
+   @Delegate
+   OSImageApi getOSImageApi();
+   
+   /**
+    * 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>
+    * @see AzureManagementAsyncApi#getOperationApi()
+    */
+   @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>
+    * @see AzureManagementAsyncApi#getDiskApi()
+    */
+   @Delegate
+   DiskApi getDiskApi();
+}
diff --git a/labs/azure-management/src/main/java/org/jclouds/azure/management/AzureManagementApiMetadata.java b/labs/azure-management/src/main/java/org/jclouds/azure/management/AzureManagementApiMetadata.java
new file mode 100644
index 0000000..5860340
--- /dev/null
+++ b/labs/azure-management/src/main/java/org/jclouds/azure/management/AzureManagementApiMetadata.java
@@ -0,0 +1,100 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.azure.management;
+
+import static org.jclouds.azure.management.config.AzureManagementProperties.SUBSCRIPTION_ID;
+
+import java.net.URI;
+import java.util.Properties;
+
+import org.jclouds.apis.ApiMetadata;
+import org.jclouds.azure.management.compute.config.AzureManagementComputeServiceContextModule;
+import org.jclouds.azure.management.config.AzureManagementRestClientModule;
+import org.jclouds.compute.ComputeServiceContext;
+import org.jclouds.rest.RestContext;
+import org.jclouds.rest.internal.BaseRestApiMetadata;
+
+import com.google.common.collect.ImmutableSet;
+import com.google.common.reflect.TypeToken;
+import com.google.inject.Module;
+
+/**
+ * Implementation of {@link ApiMetadata} for Microsoft Service Management Service API
+ * 
+ * @author Gerald Pereira
+ */
+public class AzureManagementApiMetadata extends BaseRestApiMetadata {
+   /** The serialVersionUID */
+   private static final long serialVersionUID = 8067252472547486854L;
+
+   public static final TypeToken<RestContext<AzureManagementApi, AzureManagementAsyncApi>> CONTEXT_TOKEN = new TypeToken<RestContext<AzureManagementApi, AzureManagementAsyncApi>>() {
+      private static final long serialVersionUID = -5070937833892503232L;
+   };
+
+   private static Builder builder() {
+      return new Builder();
+   }
+
+   @Override
+   public Builder toBuilder() {
+      return builder().fromApiMetadata(this);
+   }
+
+   public AzureManagementApiMetadata() {
+      this(builder());
+   }
+
+   protected AzureManagementApiMetadata(Builder builder) {
+      super(builder);
+   }
+
+   public static Properties defaultProperties() {
+      Properties properties = BaseRestApiMetadata.defaultProperties();
+      return properties;
+   }
+
+   public static class Builder extends BaseRestApiMetadata.Builder {
+      protected Builder() {
+         super(AzureManagementApi.class, AzureManagementAsyncApi.class);
+         id("azure-management")
+         .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())
+         .view(TypeToken.of(ComputeServiceContext.class))
+         .defaultModules(ImmutableSet.<Class<? extends Module>> of(AzureManagementComputeServiceContextModule.class, AzureManagementRestClientModule.class));
+      }
+
+      @Override
+      public AzureManagementApiMetadata build() {
+         return new AzureManagementApiMetadata(this);
+      }
+
+      @Override
+      public Builder fromApiMetadata(ApiMetadata in) {
+         super.fromApiMetadata(in);
+         return this;
+      }
+   }
+
+}
diff --git a/labs/azure-management/src/main/java/org/jclouds/azure/management/AzureManagementAsyncApi.java b/labs/azure-management/src/main/java/org/jclouds/azure/management/AzureManagementAsyncApi.java
new file mode 100644
index 0000000..21e8d5e
--- /dev/null
+++ b/labs/azure-management/src/main/java/org/jclouds/azure/management/AzureManagementAsyncApi.java
@@ -0,0 +1,97 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.azure.management;
+
+import org.jclouds.azure.management.features.DiskAsyncApi;
+import org.jclouds.azure.management.features.HostedServiceAsyncApi;
+import org.jclouds.azure.management.features.LocationAsyncApi;
+import org.jclouds.azure.management.features.OSImageAsyncApi;
+import org.jclouds.azure.management.features.OperationAsyncApi;
+import org.jclouds.azure.management.features.RoleAsyncApi;
+import org.jclouds.rest.annotations.Delegate;
+
+/**
+ * The Windows Azure Service Management API is a REST API for managing your services and
+ * deployments.
+ * <p/>
+ * 
+ * @see AzureManagementApi
+ * @see <a href="http://msdn.microsoft.com/en-us/library/ee460799" >doc</a>
+ * @author Gerald Pereira, Adrian Cole
+ */
+public interface AzureManagementAsyncApi {
+   /**
+    * 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>
+    * @see AzureManagementApi#getLocationApi()
+    */
+   @Delegate
+   LocationAsyncApi 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>
+    * @see AzureManagementApi#getHostedServiceApi()
+    */
+   @Delegate
+   HostedServiceAsyncApi 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>
+    * @see AzureManagementApi#getRoleApi()
+    */
+   @Delegate
+   RoleAsyncApi getRoleApi();
+   
+   /**
+    * 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>
+    * @see AzureManagementApi#getOSImageApi()
+    */
+   @Delegate
+   OSImageAsyncApi getOSImageApi();
+   
+   /**
+    * 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>
+    * @see AzureManagementApi#getOperationApi()
+    */
+   @Delegate
+   OperationAsyncApi 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>
+    * @see AzureManagementApi#getDiskApi()
+    */
+   @Delegate
+   DiskAsyncApi getDiskApi();
+}
diff --git a/labs/azure-management/src/main/java/org/jclouds/azure/management/AzureManagementProviderMetadata.java b/labs/azure-management/src/main/java/org/jclouds/azure/management/AzureManagementProviderMetadata.java
new file mode 100644
index 0000000..b52a63e
--- /dev/null
+++ b/labs/azure-management/src/main/java/org/jclouds/azure/management/AzureManagementProviderMetadata.java
@@ -0,0 +1,87 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.azure.management;
+
+import static org.jclouds.azure.management.config.AzureManagementProperties.SUBSCRIPTION_ID;
+
+import java.net.URI;
+import java.util.Properties;
+
+import org.jclouds.providers.ProviderMetadata;
+import org.jclouds.providers.internal.BaseProviderMetadata;
+
+/**
+ * Implementation of {@link org.jclouds.types.ProviderMetadata} for Microsoft Azure Service
+ * Management Service.
+ * 
+ * @author Gerald Pereira
+ */
+public class AzureManagementProviderMetadata extends BaseProviderMetadata {
+
+   /** The serialVersionUID */
+   private static final long serialVersionUID = 8271570736207734777L;
+
+   public static Builder builder() {
+      return new Builder();
+   }
+
+   @Override
+   public Builder toBuilder() {
+      return builder().fromProviderMetadata(this);
+   }
+
+   public AzureManagementProviderMetadata() {
+      super(builder());
+   }
+
+   public AzureManagementProviderMetadata(Builder builder) {
+      super(builder);
+   }
+
+   public static Properties defaultProperties() {
+      Properties properties = new Properties();
+      return properties;
+   }
+
+   public static class Builder extends BaseProviderMetadata.Builder {
+
+      protected Builder() {
+         id("azure-management")
+         .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(AzureManagementProviderMetadata.defaultProperties());
+      }
+
+      @Override
+      public AzureManagementProviderMetadata build() {
+         return new AzureManagementProviderMetadata(this);
+      }
+
+      @Override
+      public Builder fromProviderMetadata(ProviderMetadata in) {
+         super.fromProviderMetadata(in);
+         return this;
+      }
+   }
+}
diff --git a/labs/azure-management/src/main/java/org/jclouds/azure/management/binders/BindCreateHostedServiceToXmlPayload.java b/labs/azure-management/src/main/java/org/jclouds/azure/management/binders/BindCreateHostedServiceToXmlPayload.java
new file mode 100644
index 0000000..770062d
--- /dev/null
+++ b/labs/azure-management/src/main/java/org/jclouds/azure/management/binders/BindCreateHostedServiceToXmlPayload.java
@@ -0,0 +1,89 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.azure.management.binders;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.util.Map;
+import java.util.Map.Entry;
+
+import javax.inject.Singleton;
+
+import org.jclouds.azure.management.options.CreateHostedServiceOptions;
+import org.jclouds.crypto.CryptoStreams;
+import org.jclouds.http.HttpRequest;
+import org.jclouds.rest.MapBinder;
+
+import com.google.common.base.Optional;
+import com.google.common.base.Throwables;
+import com.jamesmurty.utils.XMLBuilder;
+
+/**
+ * 
+ * @author Adrian Cole
+ * 
+ */
+@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("serviceName"), "serviceName").toString();
+      String label = CryptoStreams.base64(checkNotNull(postParams.get("label"), "label").toString().getBytes());
+
+      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");
+   }
+
+}
diff --git a/labs/azure-management/src/main/java/org/jclouds/azure/management/binders/BindDeploymentParamsToXmlPayload.java b/labs/azure-management/src/main/java/org/jclouds/azure/management/binders/BindDeploymentParamsToXmlPayload.java
new file mode 100644
index 0000000..60b956b
--- /dev/null
+++ b/labs/azure-management/src/main/java/org/jclouds/azure/management/binders/BindDeploymentParamsToXmlPayload.java
@@ -0,0 +1,146 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.azure.management.binders;
+
+import javax.inject.Singleton;
+
+import org.jclouds.azure.management.domain.DeploymentParams;
+import org.jclouds.azure.management.domain.InputEndpoint;
+import org.jclouds.azure.management.domain.OSType;
+import org.jclouds.http.HttpRequest;
+import org.jclouds.rest.Binder;
+
+import com.google.common.base.Throwables;
+import com.jamesmurty.utils.XMLBuilder;
+
+/**
+ * 
+ * @author gpereira
+ *
+ */
+@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("http://"+params.getStorageAccount()+".blob.core.windows.net/disks/"+params.getName()+"/"+params.getSourceImageName()).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
+    	  
+                  
+//          builder.e("ConfigurationSet") // Network
+//                  .e("ConfigurationSetType").t("NetworkConfiguration").up()
+//                  .e("InputEndpoints");
+//          
+//          
+//        
+//          
+//          
+//          builder.up()//InputEndpoints
+//                  .e("SubnetNames").up()              
+//                  .up()//Network ConfigurationSet
+//                  .up()//ConfigurationSets
+//                  .e("DataVirtualHardDisks").up()
+//                  .e("OSVirtualHardDisk")
+//                  .e("HostCaching").t("ReadWrite").up()
+//                  .e("MediaLink").t("http://"+params.getStorageAccount()+".blob.core.windows.net/disks/"+params.getName()+"/"+params.getSourceImageName()).up()
+//                  .e("SourceImageName").t(params.getSourceImageName()).up()
+//                  .e("OS").t("Linux").up()
+//                  .up()//OSVirtualHardDisk
+//                  .e("RoleSize").t(params.getSize().name()).up()
+//                  .up()//Role
+//                  .up();//RoleList
+						 
+    	  
+    	  
+         return (R) request.toBuilder().payload(builder.asString()).build();
+      } catch (Exception e) {
+         throw Throwables.propagate(e);
+      }
+
+   }
+
+}
diff --git a/labs/azure-management/src/main/java/org/jclouds/azure/management/binders/BindOSImageParamsToXmlPayload.java b/labs/azure-management/src/main/java/org/jclouds/azure/management/binders/BindOSImageParamsToXmlPayload.java
new file mode 100644
index 0000000..0d413bd
--- /dev/null
+++ b/labs/azure-management/src/main/java/org/jclouds/azure/management/binders/BindOSImageParamsToXmlPayload.java
@@ -0,0 +1,55 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.azure.management.binders;
+
+import javax.inject.Singleton;
+
+import org.jclouds.azure.management.domain.OSImageParams;
+import org.jclouds.http.HttpRequest;
+import org.jclouds.rest.Binder;
+
+import com.google.common.base.Throwables;
+import com.jamesmurty.utils.XMLBuilder;
+
+/**
+ * 
+ * @author Adrian Cole
+ * 
+ */
+@Singleton
+public class BindOSImageParamsToXmlPayload implements Binder {
+
+
+   @Override
+   public <R extends HttpRequest> R bindToRequest(R request, Object input) {
+      OSImageParams params = OSImageParams.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);
+      }
+
+   }
+
+}
diff --git a/labs/azure-management/src/main/java/org/jclouds/azure/management/compute/AzureManagementComputeServiceAdapter.java b/labs/azure-management/src/main/java/org/jclouds/azure/management/compute/AzureManagementComputeServiceAdapter.java
new file mode 100644
index 0000000..a27f026
--- /dev/null
+++ b/labs/azure-management/src/main/java/org/jclouds/azure/management/compute/AzureManagementComputeServiceAdapter.java
@@ -0,0 +1,129 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.azure.management.compute;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import javax.annotation.Resource;
+import javax.inject.Inject;
+import javax.inject.Named;
+import javax.inject.Singleton;
+
+import org.jclouds.azure.management.AzureManagementApi;
+import org.jclouds.azure.management.AzureManagementAsyncApi;
+import org.jclouds.azure.management.domain.Deployment;
+import org.jclouds.azure.management.domain.OSImage;
+import org.jclouds.azure.management.domain.RoleSize;
+import org.jclouds.compute.ComputeService;
+import org.jclouds.compute.ComputeServiceAdapter;
+import org.jclouds.compute.domain.Template;
+import org.jclouds.compute.reference.ComputeServiceConstants;
+import org.jclouds.logging.Logger;
+
+/**
+ * defines the connection between the {@link AzureApi} implementation and the
+ * jclouds {@link ComputeService}
+ * 
+ */
+@Singleton
+public class AzureManagementComputeServiceAdapter implements
+		ComputeServiceAdapter<Deployment, RoleSize, OSImage, String> {
+
+	@Resource
+	@Named(ComputeServiceConstants.COMPUTE_LOGGER)
+	protected Logger logger = Logger.NULL;
+
+	private final AzureManagementApi api;
+	private final AzureManagementAsyncApi aapi;
+
+	@Inject
+	public AzureManagementComputeServiceAdapter(AzureManagementApi api,
+			AzureManagementAsyncApi aapi) {
+		this.api = checkNotNull(api, "api");
+		this.aapi = checkNotNull(aapi, "aapi");
+	}
+
+	@Override
+	public org.jclouds.compute.ComputeServiceAdapter.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<OSImage> listImages() {
+		// TODO Auto-generated method stub
+		return null;
+	}
+
+	@Override
+	public OSImage 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;
+	}
+
+}
diff --git a/labs/azure-management/src/main/java/org/jclouds/azure/management/compute/config/AzureManagementComputeServiceContextModule.java b/labs/azure-management/src/main/java/org/jclouds/azure/management/compute/config/AzureManagementComputeServiceContextModule.java
new file mode 100644
index 0000000..4e1237a
--- /dev/null
+++ b/labs/azure-management/src/main/java/org/jclouds/azure/management/compute/config/AzureManagementComputeServiceContextModule.java
@@ -0,0 +1,58 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.azure.management.compute.config;
+
+import org.jclouds.azure.management.compute.AzureManagementComputeServiceAdapter;
+import org.jclouds.azure.management.compute.functions.DeploymentToNodeMetadata;
+import org.jclouds.azure.management.compute.functions.OSImageToImage;
+import org.jclouds.azure.management.compute.functions.RoleSizeToHardware;
+import org.jclouds.azure.management.domain.Deployment;
+import org.jclouds.azure.management.domain.OSImage;
+import org.jclouds.azure.management.domain.RoleSize;
+import org.jclouds.compute.ComputeServiceAdapter;
+import org.jclouds.compute.config.ComputeServiceAdapterContextModule;
+import org.jclouds.compute.domain.Hardware;
+import org.jclouds.compute.domain.Image;
+import org.jclouds.compute.domain.NodeMetadata;
+
+import com.google.common.base.Function;
+import com.google.inject.TypeLiteral;
+
+/**
+ * 
+ * @author Gérald Pereira
+ */
+public class AzureManagementComputeServiceContextModule extends
+         ComputeServiceAdapterContextModule<Deployment, RoleSize, OSImage, String> {
+
+   @Override
+   protected void configure() {
+      super.configure();
+      bind(new TypeLiteral<ComputeServiceAdapter<Deployment, RoleSize, OSImage, String>>() {
+      }).to(AzureManagementComputeServiceAdapter.class);
+      bind(new TypeLiteral<Function<OSImage, Image>>() {
+      }).to(OSImageToImage.class);
+      bind(new TypeLiteral<Function<RoleSize, Hardware>>() {
+      }).to(RoleSizeToHardware.class);
+      bind(new TypeLiteral<Function<Deployment, NodeMetadata>>() {
+      }).to(DeploymentToNodeMetadata.class);
+      
+   }
+
+}
diff --git a/labs/azure-management/src/main/java/org/jclouds/azure/management/compute/functions/DeploymentToNodeMetadata.java b/labs/azure-management/src/main/java/org/jclouds/azure/management/compute/functions/DeploymentToNodeMetadata.java
new file mode 100644
index 0000000..a4052bc
--- /dev/null
+++ b/labs/azure-management/src/main/java/org/jclouds/azure/management/compute/functions/DeploymentToNodeMetadata.java
@@ -0,0 +1,15 @@
+package org.jclouds.azure.management.compute.functions;
+
+import org.jclouds.azure.management.domain.Deployment;
+import org.jclouds.compute.domain.NodeMetadata;
+
+import com.google.common.base.Function;
+
+public class DeploymentToNodeMetadata implements Function<Deployment, NodeMetadata> {
+
+	@Override
+	public NodeMetadata apply(Deployment input) {
+		return null;
+	}
+
+}
diff --git a/labs/azure-management/src/main/java/org/jclouds/azure/management/compute/functions/OSImageToImage.java b/labs/azure-management/src/main/java/org/jclouds/azure/management/compute/functions/OSImageToImage.java
new file mode 100644
index 0000000..5077aa9
--- /dev/null
+++ b/labs/azure-management/src/main/java/org/jclouds/azure/management/compute/functions/OSImageToImage.java
@@ -0,0 +1,15 @@
+package org.jclouds.azure.management.compute.functions;
+
+import org.jclouds.azure.management.domain.OSImage;
+import org.jclouds.compute.domain.Image;
+
+import com.google.common.base.Function;
+
+public class OSImageToImage implements Function<OSImage, Image>{
+
+	@Override
+	public Image apply(OSImage input) {
+		return null;
+	}
+
+}
diff --git a/labs/azure-management/src/main/java/org/jclouds/azure/management/compute/functions/RoleSizeToHardware.java b/labs/azure-management/src/main/java/org/jclouds/azure/management/compute/functions/RoleSizeToHardware.java
new file mode 100644
index 0000000..85b5388
--- /dev/null
+++ b/labs/azure-management/src/main/java/org/jclouds/azure/management/compute/functions/RoleSizeToHardware.java
@@ -0,0 +1,15 @@
+package org.jclouds.azure.management.compute.functions;
+
+import org.jclouds.azure.management.domain.RoleSize;
+import org.jclouds.compute.domain.Hardware;
+
+import com.google.common.base.Function;
+
+public class RoleSizeToHardware implements Function<RoleSize, Hardware> {
+
+	@Override
+	public Hardware apply(RoleSize input) {
+		return null;
+	}
+
+}
diff --git a/labs/azure-management/src/main/java/org/jclouds/azure/management/config/AzureManagementProperties.java b/labs/azure-management/src/main/java/org/jclouds/azure/management/config/AzureManagementProperties.java
new file mode 100644
index 0000000..964710f
--- /dev/null
+++ b/labs/azure-management/src/main/java/org/jclouds/azure/management/config/AzureManagementProperties.java
@@ -0,0 +1,40 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.azure.management.config;
+
+/**
+ * Configuration properties and constants used in Azure Service Management
+ * connections.
+ * 
+ * @author Gerald Pereira
+ */
+public class AzureManagementProperties {
+	/**
+	 * 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 final static String SUBSCRIPTION_ID = "jclouds.azure.management.subscription-id";
+}
diff --git a/labs/azure-management/src/main/java/org/jclouds/azure/management/config/AzureManagementRestClientModule.java b/labs/azure-management/src/main/java/org/jclouds/azure/management/config/AzureManagementRestClientModule.java
new file mode 100644
index 0000000..132669a
--- /dev/null
+++ b/labs/azure-management/src/main/java/org/jclouds/azure/management/config/AzureManagementRestClientModule.java
@@ -0,0 +1,151 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.azure.management.config;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.PrivateKey;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateFactory;
+import java.security.spec.InvalidKeySpecException;
+import java.security.spec.KeySpec;
+import java.util.Collection;
+import java.util.Map;
+
+import javax.inject.Singleton;
+import javax.net.ssl.SSLContext;
+
+import org.jclouds.azure.management.AzureManagementApi;
+import org.jclouds.azure.management.AzureManagementAsyncApi;
+import org.jclouds.azure.management.features.DiskApi;
+import org.jclouds.azure.management.features.DiskAsyncApi;
+import org.jclouds.azure.management.features.HostedServiceApi;
+import org.jclouds.azure.management.features.HostedServiceAsyncApi;
+import org.jclouds.azure.management.features.LocationApi;
+import org.jclouds.azure.management.features.LocationAsyncApi;
+import org.jclouds.azure.management.features.OSImageApi;
+import org.jclouds.azure.management.features.OSImageAsyncApi;
+import org.jclouds.azure.management.features.OperationApi;
+import org.jclouds.azure.management.features.OperationAsyncApi;
+import org.jclouds.azure.management.features.RoleApi;
+import org.jclouds.azure.management.features.RoleAsyncApi;
+import org.jclouds.azure.management.suppliers.SSLContextWithKeysSupplier;
+import org.jclouds.crypto.Crypto;
+import org.jclouds.crypto.Pems;
+import org.jclouds.io.InputSuppliers;
+import org.jclouds.rest.ConfiguresRestClient;
+import org.jclouds.rest.annotations.Credential;
+import org.jclouds.rest.annotations.Identity;
+import org.jclouds.rest.config.RestClientModule;
+
+import com.google.common.base.Supplier;
+import com.google.common.collect.ImmutableMap;
+import com.google.inject.Provides;
+import com.google.inject.TypeLiteral;
+
+/**
+ * Configures the Azure Service Management connection.
+ * 
+ * @author Gerald Pereira
+ */
+@ConfiguresRestClient
+public class AzureManagementRestClientModule extends RestClientModule<AzureManagementApi, AzureManagementAsyncApi> {
+   public static final Map<Class<?>, Class<?>> DELEGATE_MAP = ImmutableMap.<Class<?>, Class<?>> builder()
+            .put(LocationApi.class, LocationAsyncApi.class)
+            .put(RoleApi.class, RoleAsyncApi.class)
+            .put(HostedServiceApi.class, HostedServiceAsyncApi.class)
+            .put(OSImageApi.class, OSImageAsyncApi.class)
+            .put(OperationApi.class, OperationAsyncApi.class)
+            .put(DiskApi.class, DiskAsyncApi.class)
+            .build();
+
+   public AzureManagementRestClientModule() {
+      super(DELEGATE_MAP);
+   }
+
+   @Override
+   protected void configure() {
+      super.configure();
+      bind(new TypeLiteral<Supplier<SSLContext>>() {
+      }).to(new TypeLiteral<SSLContextWithKeysSupplier>() {
+      });
+   }
+
+   /**
+    * TODO copied from FGCP, should be put in a common place
+    * 
+    * @author Dies Koper
+    */
+   @Provides
+   @Singleton
+   protected KeyStore provideKeyStore(Crypto crypto, @Identity String cert, @Credential String keyStorePassword)
+            throws KeyStoreException, IOException, NoSuchAlgorithmException, CertificateException,
+            InvalidKeySpecException {
+      KeyStore keyStore = KeyStore.getInstance("PKCS12");
+
+      File certFile = new File(checkNotNull(cert));
+      if (certFile.isFile()) { // cert is path to pkcs12 file
+
+         keyStore.load(new FileInputStream(certFile), keyStorePassword.toCharArray());
+      } else { // cert is PEM encoded, containing private key and certs
+
+         // split in private key and certs
+         int privateKeyBeginIdx = cert.indexOf("-----BEGIN PRIVATE KEY");
+         int privateKeyEndIdx = cert.indexOf("-----END PRIVATE KEY");
+         String pemPrivateKey = cert.substring(privateKeyBeginIdx, privateKeyEndIdx + 26);
+
+         String pemCerts = "";
+         int certsBeginIdx = 0;
+
+         do {
+            certsBeginIdx = cert.indexOf("-----BEGIN CERTIFICATE", certsBeginIdx);
+
+            if (certsBeginIdx >= 0) {
+               int certsEndIdx = cert.indexOf("-----END CERTIFICATE", certsBeginIdx) + 26;
+               pemCerts += cert.substring(certsBeginIdx, certsEndIdx);
+               certsBeginIdx = certsEndIdx;
+            }
+         } while (certsBeginIdx != -1);
+
+         // parse private key
+         KeySpec keySpec = Pems.privateKeySpec(InputSuppliers.of(pemPrivateKey));
+         PrivateKey privateKey = crypto.rsaKeyFactory().generatePrivate(keySpec);
+
+         // populate keystore with private key and certs
+         CertificateFactory cf = CertificateFactory.getInstance("X.509");
+         @SuppressWarnings("unchecked")
+         Collection<Certificate> certs = (Collection<Certificate>) cf.generateCertificates(new ByteArrayInputStream(
+                  pemCerts.getBytes("UTF-8")));
+         keyStore.load(null);
+         keyStore.setKeyEntry("dummy", privateKey, keyStorePassword.toCharArray(),
+                  certs.toArray(new java.security.cert.Certificate[0]));
+
+      }
+
+      return keyStore;
+   }
+}
diff --git a/labs/azure-management/src/main/java/org/jclouds/azure/management/domain/Deployment.java b/labs/azure-management/src/main/java/org/jclouds/azure/management/domain/Deployment.java
new file mode 100644
index 0000000..abd09a8
--- /dev/null
+++ b/labs/azure-management/src/main/java/org/jclouds/azure/management/domain/Deployment.java
@@ -0,0 +1,290 @@
+package org.jclouds.azure.management.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) {
+		super();
+		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 + "]";
+	}
+
+
+}
diff --git a/labs/azure-management/src/main/java/org/jclouds/azure/management/domain/DeploymentParams.java b/labs/azure-management/src/main/java/org/jclouds/azure/management/domain/DeploymentParams.java
new file mode 100644
index 0000000..0a6e7d2
--- /dev/null
+++ b/labs/azure-management/src/main/java/org/jclouds/azure/management/domain/DeploymentParams.java
@@ -0,0 +1,208 @@
+package org.jclouds.azure.management.domain;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import com.google.common.base.Objects;
+import com.google.common.base.Objects.ToStringHelper;
+
+/**
+ * 
+ * To create a new deployment/role
+ * 
+ * Warning : the OSType must be the one of the source image used to create the VM
+ * 
+ * @author Gérald Pereira
+ * 
+ */
+public class DeploymentParams {
+
+	public static Builder builder() {
+		return new Builder();
+	}
+
+	public Builder toBuilder() {
+		return builder().fromLinuxDeploymentParams(this);
+	}
+
+	public static class Builder {
+
+		protected String name;
+		protected String sourceImageName;
+		protected String username;
+		protected String password;
+		protected String storageAccount;
+		protected OSType osType;
+		protected RoleSize size = RoleSize.SMALL;
+		protected List<InputEndpoint> endpoints = new ArrayList<InputEndpoint>();
+
+		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 fromLinuxDeploymentParams(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());
+		}
+	}
+
+	protected final String name;
+	protected final String sourceImageName;
+	protected final String username;
+	protected final String password;
+	protected final String storageAccount;
+	protected final RoleSize size;
+	protected final OSType osType;
+	protected final List<InputEndpoint> endpoints;
+	
+	
+	public DeploymentParams(String name, String sourceImageName,
+			String username, String password, String storageAccount,
+			RoleSize size,OSType osType,final List<InputEndpoint> endpoints) {
+		super();
+		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;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public int hashCode() {
+		return Objects.hashCode(name);
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@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);
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public String toString() {
+		return string().toString();
+	}
+
+	protected ToStringHelper string() {
+		return Objects.toStringHelper(this).add("name", name)
+				.add("sourceImageName", sourceImageName).add("size", size);
+	}
+}
diff --git a/labs/azure-management/src/main/java/org/jclouds/azure/management/domain/DeploymentSlot.java b/labs/azure-management/src/main/java/org/jclouds/azure/management/domain/DeploymentSlot.java
new file mode 100644
index 0000000..1a64945
--- /dev/null
+++ b/labs/azure-management/src/main/java/org/jclouds/azure/management/domain/DeploymentSlot.java
@@ -0,0 +1,27 @@
+package org.jclouds.azure.management.domain;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import com.google.common.base.CaseFormat;
+
+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;
+		}
+	}
+}
diff --git a/labs/azure-management/src/main/java/org/jclouds/azure/management/domain/DeploymentStatus.java b/labs/azure-management/src/main/java/org/jclouds/azure/management/domain/DeploymentStatus.java
new file mode 100644
index 0000000..c57e6d8
--- /dev/null
+++ b/labs/azure-management/src/main/java/org/jclouds/azure/management/domain/DeploymentStatus.java
@@ -0,0 +1,27 @@
+package org.jclouds.azure.management.domain;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import com.google.common.base.CaseFormat;
+
+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;
+		}
+	}
+}
diff --git a/labs/azure-management/src/main/java/org/jclouds/azure/management/domain/DetailedHostedServiceProperties.java b/labs/azure-management/src/main/java/org/jclouds/azure/management/domain/DetailedHostedServiceProperties.java
new file mode 100644
index 0000000..81755ad
--- /dev/null
+++ b/labs/azure-management/src/main/java/org/jclouds/azure/management/domain/DetailedHostedServiceProperties.java
@@ -0,0 +1,188 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.azure.management.domain;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.util.Date;
+import java.util.Map;
+
+import org.jclouds.azure.management.domain.HostedService.Status;
+
+import com.google.common.base.Objects.ToStringHelper;
+import com.google.common.base.Optional;
+import com.google.common.collect.ImmutableMap;
+
+/**
+ * 
+ * @author Adrian Cole
+ */
+public class DetailedHostedServiceProperties extends HostedServiceProperties {
+   public static Builder<?> builder() {
+      return new ConcreteBuilder();
+   }
+
+   public Builder<?> toBuilder() {
+      return new ConcreteBuilder().fromDetailedHostedServiceProperties(this);
+   }
+
+   public static abstract class Builder<T extends Builder<T>> extends HostedServiceProperties.Builder<T> {
+
+      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 T rawStatus(String rawStatus) {
+         this.rawStatus = rawStatus;
+         return self();
+      }
+
+      /**
+       * @see DetailedHostedServiceProperties#getStatus()
+       */
+      public T status(Status status) {
+         this.status = status;
+         return self();
+      }
+
+      /**
+       * @see DetailedHostedServiceProperties#getCreated()
+       */
+      public T created(Date created) {
+         this.created = created;
+         return self();
+      }
+
+      /**
+       * @see DetailedHostedServiceProperties#getLastModified()
+       */
+      public T lastModified(Date lastModified) {
+         this.lastModified = lastModified;
+         return self();
+      }
+
+      /**
+       * @see DetailedHostedServiceProperties#getExtendedProperties()
+       */
+      public T extendedProperties(Map<String, String> extendedProperties) {
+         this.extendedProperties.putAll(checkNotNull(extendedProperties, "extendedProperties"));
+         return self();
+      }
+
+      /**
+       * @see DetailedHostedServiceProperties#getExtendedProperties()
+       */
+      public T addExtendedProperty(String name, String value) {
+         this.extendedProperties.put(checkNotNull(name, "name"), checkNotNull(value, "value"));
+         return self();
+      }
+
+      public DetailedHostedServiceProperties build() {
+         return new DetailedHostedServiceProperties(description, location, affinityGroup, label, rawStatus, status,
+                  created, lastModified, extendedProperties.build());
+      }
+
+      public T fromDetailedHostedServiceProperties(DetailedHostedServiceProperties in) {
+         return fromHostedServiceProperties(in).rawStatus(in.getRawStatus()).status(in.getStatus())
+                  .created(in.getCreated()).lastModified(in.getLastModified())
+                  .extendedProperties(in.getExtendedProperties());
+      }
+   }
+
+   private static class ConcreteBuilder extends Builder<ConcreteBuilder> {
+      @Override
+      protected ConcreteBuilder self() {
+         return this;
+      }
+   }
+
+   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;
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public ToStringHelper string() {
+      return super.string().add("status", rawStatus).add("created", created).add("lastModified", lastModified)
+               .add("extendedProperties", extendedProperties);
+   }
+
+}
diff --git a/labs/azure-management/src/main/java/org/jclouds/azure/management/domain/Disk.java b/labs/azure-management/src/main/java/org/jclouds/azure/management/domain/Disk.java
new file mode 100644
index 0000000..1723a32
--- /dev/null
+++ b/labs/azure-management/src/main/java/org/jclouds/azure/management/domain/Disk.java
@@ -0,0 +1,465 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.azure.management.domain;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.net.URI;
+
+import com.google.common.base.Objects;
+import com.google.common.base.Objects.ToStringHelper;
+import com.google.common.base.Optional;
+
+/**
+ * disk in the image repository
+ * 
+ * @see <a href="http://msdn.microsoft.com/en-us/library/jj157176" >api</a>
+ * @author Adrian Cole
+ */
+public class Disk {
+   public static class Attachment {
+
+      public static Builder builder() {
+         return new Builder();
+      }
+
+      public Builder toBuilder() {
+         return builder().fromAttachment(this);
+      }
+
+      public static class Builder {
+
+         private String hostedService;
+         private String deployment;
+         private String role;
+
+         /**
+          * @see Attachment#getHostedService()
+          */
+         public Builder hostedService(String hostedService) {
+            this.hostedService = hostedService;
+            return this;
+         }
+
+         /**
+          * @see Attachment#getDeployment()
+          */
+         public Builder deployment(String deployment) {
+            this.deployment = deployment;
+            return this;
+         }
+
+         /**
+          * @see Attachment#getRole()
+          */
+         public Builder role(String role) {
+            this.role = role;
+            return this;
+         }
+
+         public Attachment build() {
+            return new Attachment(hostedService, deployment, role);
+         }
+
+         public Builder fromAttachment(Attachment in) {
+            return this.hostedService(in.hostedService).deployment(in.deployment).role(in.role);
+         }
+      }
+
+      private final String hostedService;
+      private final String deployment;
+      private final String role;
+
+      protected Attachment(String hostedService, String deployment, String role) {
+         this.hostedService = checkNotNull(hostedService, "hostedService");
+         this.deployment = checkNotNull(deployment, "deployment");
+         this.role = checkNotNull(role, "role");
+      }
+
+      /**
+       * The deployment in which the disk is being used.
+       */
+      public String getDeployment() {
+         return deployment;
+      }
+
+      /**
+       * The hosted service in which the disk is being used.
+       */
+      public String getHostedService() {
+         return hostedService;
+      }
+
+      /**
+       * The virtual machine that the disk is attached to.
+       */
+      public String getRole() {
+         return role;
+      }
+
+      /**
+       * {@inheritDoc}
+       */
+      @Override
+      public int hashCode() {
+         return Objects.hashCode(hostedService, deployment, role);
+      }
+
+      /**
+       * {@inheritDoc}
+       */
+      @Override
+      public boolean equals(Object obj) {
+         if (this == obj)
+            return true;
+         if (obj == null)
+            return false;
+         if (getClass() != obj.getClass())
+            return false;
+         Attachment other = (Attachment) obj;
+         return Objects.equal(this.hostedService, other.hostedService)
+                  && Objects.equal(this.deployment, other.deployment) && Objects.equal(this.role, other.role);
+      }
+
+      /**
+       * {@inheritDoc}
+       */
+      @Override
+      public String toString() {
+         return Objects.toStringHelper(this).omitNullValues().add("deployment", hostedService).add("role", role)
+                  .toString();
+      }
+
+   }
+
+   public static Builder<?> builder() {
+      return new ConcreteBuilder();
+   }
+
+   public Builder<?> toBuilder() {
+      return new ConcreteBuilder().fromHostedService(this);
+   }
+
+   public static abstract class Builder<T extends Builder<T>> {
+      protected abstract T self();
+
+      protected Optional<Attachment> attachedTo = Optional.absent();
+      protected OSType os;
+      protected String name;
+      protected Optional<Integer> logicalSizeInGB = Optional.absent();
+      protected Optional<String> description = Optional.absent();
+      protected Optional<String> location = Optional.absent();
+      protected Optional<String> affinityGroup = Optional.absent();
+      protected Optional<URI> mediaLink = Optional.absent();
+      protected Optional<String> sourceImage = Optional.absent();
+      protected Optional<String> label = Optional.absent();
+      protected boolean hasOperatingSystem;
+      protected boolean isCorrupted;
+
+      /**
+       * @see Disk#getAttachedTo()
+       */
+      public T attachedTo(Attachment attachedTo) {
+         this.attachedTo = Optional.fromNullable(attachedTo);
+         return self();
+      }
+
+      /**
+       * @see Disk#getOS()
+       */
+      public T os(OSType os) {
+         this.os = os;
+         return self();
+      }
+
+      /**
+       * @see Disk#getName()
+       */
+      public T name(String name) {
+         this.name = name;
+         return self();
+      }
+
+      /**
+       * @see Disk#getDescription()
+       */
+      public T description(String description) {
+         this.description = Optional.fromNullable(description);
+         return self();
+      }
+
+      /**
+       * @see Disk#getLogicalSizeInGB()
+       */
+      public T logicalSizeInGB(Integer logicalSizeInGB) {
+         this.logicalSizeInGB = Optional.fromNullable(logicalSizeInGB);
+         return self();
+      }
+
+      /**
+       * @see Disk#getLocation()
+       */
+      public T location(String location) {
+         this.location = Optional.fromNullable(location);
+         return self();
+      }
+
+      /**
+       * @see Disk#getAffinityGroup()
+       */
+      public T affinityGroup(String affinityGroup) {
+         this.affinityGroup = Optional.fromNullable(affinityGroup);
+         return self();
+      }
+
+      /**
+       * @see Disk#getMediaLink()
+       */
+      public T mediaLink(URI mediaLink) {
+         this.mediaLink = Optional.fromNullable(mediaLink);
+         return self();
+      }
+
+      /**
+       * @see Disk#getSourceImage()
+       */
+      public T sourceImage(String sourceImage) {
+         this.sourceImage = Optional.fromNullable(sourceImage);
+         return self();
+      }
+
+      /**
+       * @see Disk#getLabel()
+       */
+      public T label(String label) {
+         this.label = Optional.fromNullable(label);
+         return self();
+      }
+
+      /**
+       * @see Disk#hasOperatingSystem()
+       */
+      public T hasOperatingSystem(boolean hasOperatingSystem) {
+         this.hasOperatingSystem = hasOperatingSystem;
+         return self();
+      }
+
+      /**
+       * @see Disk#isCorrupted()
+       */
+      public T isCorrupted(boolean isCorrupted) {
+         this.isCorrupted = isCorrupted;
+         return self();
+      }
+
+      public Disk build() {
+         return new Disk(attachedTo, os, name, logicalSizeInGB, description, location, affinityGroup, mediaLink,
+                  sourceImage, label, hasOperatingSystem, isCorrupted);
+      }
+
+      public T fromHostedService(Disk in) {
+         return this.attachedTo(in.attachedTo.orNull()).os(in.getOS()).name(in.getName())
+                  .logicalSizeInGB(in.getLogicalSizeInGB().orNull()).description(in.getDescription().orNull())
+                  .location(in.getLocation().orNull()).affinityGroup(in.getAffinityGroup().orNull())
+                  .mediaLink(in.getMediaLink().orNull()).sourceImage(in.getSourceImage().orNull())
+                  .label(in.getLabel().orNull()).hasOperatingSystem(in.hasOperatingSystem).isCorrupted(in.isCorrupted);
+      }
+   }
+
+   private static class ConcreteBuilder extends Builder<ConcreteBuilder> {
+      @Override
+      protected ConcreteBuilder self() {
+         return this;
+      }
+   }
+
+   protected final Optional<Attachment> attachedTo;
+   protected final OSType os;
+   protected final String name;
+   protected final Optional<Integer> logicalSizeInGB;
+   protected final Optional<String> description;
+   protected final Optional<String> location;
+   protected final Optional<String> affinityGroup;
+   protected final Optional<URI> mediaLink;
+   protected final Optional<String> sourceImage;
+   protected final Optional<String> label;
+   protected final boolean hasOperatingSystem;
+   protected final boolean isCorrupted;
+
+   protected Disk(Optional<Attachment> attachedTo, OSType os, String name, Optional<Integer> logicalSizeInGB,
+            Optional<String> description, Optional<String> location, Optional<String> affinityGroup,
+            Optional<URI> mediaLink, Optional<String> sourceImage, Optional<String> label, boolean hasOperatingSystem,
+            boolean isCorrupted) {
+      this.name = checkNotNull(name, "name");
+      this.attachedTo = checkNotNull(attachedTo, "attachedTo for %s", name);
+      this.logicalSizeInGB = checkNotNull(logicalSizeInGB, "logicalSizeInGB for %s", name);
+      this.description = checkNotNull(description, "description for %s", name);
+      this.os = checkNotNull(os, "os for %s", name);
+      this.location = checkNotNull(location, "location for %s", name);
+      this.affinityGroup = checkNotNull(affinityGroup, "affinityGroup for %s", name);
+      this.mediaLink = checkNotNull(mediaLink, "mediaLink for %s", name);
+      this.sourceImage = checkNotNull(sourceImage, "sourceImage for %s", name);
+      this.label = checkNotNull(label, "label for %s", name);
+      this.hasOperatingSystem = hasOperatingSystem;
+      this.isCorrupted = isCorrupted;
+   }
+
+   /**
+    * Contains properties that specify a virtual machine that currently using the disk. A disk
+    * cannot be deleted as long as it is attached to a virtual machine.
+    */
+   public Optional<Attachment> getAttachedTo() {
+      return attachedTo;
+   }
+
+   /**
+    * The operating system type of the OS image.
+    */
+   public OSType getOS() {
+      return os;
+   }
+
+   /**
+    * The name of the disk. This is the name that is used when creating one or more virtual machines
+    * using the disk.
+    */
+   public String getName() {
+      return name;
+   }
+
+   /**
+    * The size, in GB, of the image.
+    */
+   public Optional<Integer> getLogicalSizeInGB() {
+      return logicalSizeInGB;
+   }
+
+   /**
+    * The description for the image.
+    */
+   public Optional<String> getDescription() {
+      return description;
+   }
+
+   /**
+    * The geo-location in which this media is located. The Location value is derived from storage
+    * account that contains the blob in which the media is located. If the storage account belongs
+    * to an affinity group the value is absent.
+    */
+   public Optional<String> getLocation() {
+      return location;
+   }
+
+   /**
+    * The affinity in which the media is located. The AffinityGroup value is derived from storage
+    * account that contains the blob in which the media is located. If the storage account does not
+    * belong to an affinity group the value is absent.
+    */
+   public Optional<String> getAffinityGroup() {
+      return affinityGroup;
+   }
+
+   /**
+    * The location of the blob in the blob store in which the media for the disk is located. The
+    * blob location belongs to a storage account in the subscription specified by the
+    * <subscription-id> value in the operation call.
+    * 
+    * Example:
+    * 
+    * http://example.blob.core.windows.net/disks/mydisk.vhd
+    */
+   public Optional<URI> getMediaLink() {
+      return mediaLink;
+   }
+
+   /**
+    * The name of the OS Image from which the disk was created. This property is populated
+    * automatically when a disk is created from an OS image by calling the Add Role, Create
+    * Deployment, or Provision Disk operations.
+    */
+   public Optional<String> getSourceImage() {
+      return sourceImage;
+   }
+
+   /**
+    * The description of the image.
+    */
+   public Optional<String> getLabel() {
+      return label;
+   }
+
+   /**
+    * Returns whether this disk contains operation system. Only disks that have an operating system
+    * installed can be mounted as an OS Drive.
+    */
+   public boolean hasOperatingSystem() {
+      return hasOperatingSystem;
+   }
+
+   /**
+    * Returns whether there is a consistency failure detected with this disk. If a disk fails the
+    * consistency check, you delete any virtual machines using it, delete the disk, and inspect the
+    * blob media to see if the content is intact. You can then reregister the media in the blob as a
+    * disk.
+    */
+   public boolean isCorrupted() {
+      return isCorrupted;
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public int hashCode() {
+      return Objects.hashCode(name);
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public boolean equals(Object obj) {
+      if (this == obj)
+         return true;
+      if (obj == null)
+         return false;
+      if (getClass() != obj.getClass())
+         return false;
+      Disk other = (Disk) obj;
+      return Objects.equal(this.name, other.name);
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public String toString() {
+      return string().toString();
+   }
+
+   protected ToStringHelper string() {
+      return Objects.toStringHelper(this).omitNullValues().add("os", os).add("name", name)
+               .add("attachedTo", attachedTo.orNull()).add("logicalSizeInGB", logicalSizeInGB.orNull())
+               .add("description", description).add("location", location.orNull())
+               .add("affinityGroup", affinityGroup.orNull()).add("mediaLink", mediaLink.orNull())
+               .add("sourceImage", sourceImage.orNull()).add("label", label.orNull())
+               .add("hasOperatingSystem", hasOperatingSystem).add("isCorrupted", isCorrupted);
+   }
+
+}
diff --git a/labs/azure-management/src/main/java/org/jclouds/azure/management/domain/Error.java b/labs/azure-management/src/main/java/org/jclouds/azure/management/domain/Error.java
new file mode 100644
index 0000000..623446c
--- /dev/null
+++ b/labs/azure-management/src/main/java/org/jclouds/azure/management/domain/Error.java
@@ -0,0 +1,253 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.azure.management.domain;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import com.google.common.base.CaseFormat;
+import com.google.common.base.Objects;
+
+/**
+ * additional error information that is defined by the management service. Th
+ * 
+ * @see <a href="http://msdn.microsoft.com/en-us/library/ee460801" >api</a>
+ * 
+ * @author Adrian Cole
+ */
+public class Error {
+
+   public static enum Code {
+
+      /**
+       * Bad Request (400)
+       * 
+       * The versioning header is not specified or was specified incorrectly.
+       */
+      MISSING_OR_INCORRECT_VERSION_HEADER,
+
+      /**
+       * Bad Request (400)
+       * 
+       * The request body’s XML was invalid or not correctly specified.
+       */
+      INVALID_XML_REQUEST,
+
+      /**
+       * Bad Request (400)
+       * 
+       * A required query parameter was not specified for this request or was specified incorrectly.
+       */
+      MISSING_OR_INVALID_REQUIRED_QUERY_PARAMETER,
+
+      /**
+       * Bad Request (400)
+       * 
+       * The HTTP verb specified was not recognized by the server or isn’t valid for this resource.
+       */
+      INVALID_HTTP_VERB,
+
+      /**
+       * Forbidden (403)
+       * 
+       * The server failed to authenticate the request. Verify that the certificate is valid and is
+       * associated with this subscription.
+       */
+      AUTHENTICATION_FAILED,
+
+      /**
+       * Not Found (404)
+       * 
+       * The specified resource does not exist.
+       */
+      RESOURCE_NOT_FOUND,
+
+      /**
+       * Internal Server Error (500)
+       * 
+       * The server encountered an internal error. Please retry the request.
+       */
+      INTERNAL_ERROR,
+
+      /**
+       * Internal Server Error (500)
+       * 
+       * The operation could not be completed within the permitted time.
+       */
+      OPERATION_TIMED_OUT,
+
+      /**
+       * Service Unavailable (503)
+       * 
+       * The server (or an internal component) is currently unavailable to receive requests. Please
+       * retry your request
+       */
+      SERVER_BUSY,
+
+      /**
+       * Forbidden (403)
+       * 
+       * The subscription is in a disabled state.
+       */
+      SUBSCRIPTION_DISABLED,
+
+      /**
+       * Bad Request (400)
+       * 
+       * A parameter was incorrect.
+       */
+      BAD_REQUEST,
+
+      /**
+       * Conflict (409)
+       * 
+       * A conflict occurred to prevent the operation from completing.
+       */
+      CONFLICT_ERROR,
+
+      UNRECOGNIZED;
+
+      public String value() {
+         return CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.UPPER_CAMEL, name());
+      }
+
+      @Override
+      public String toString() {
+         return value();
+      }
+
+      public static Code fromValue(String code) {
+         try {
+            return valueOf(CaseFormat.UPPER_CAMEL.to(CaseFormat.UPPER_UNDERSCORE, checkNotNull(code, "code")));
+         } catch (IllegalArgumentException e) {
+            return UNRECOGNIZED;
+         }
+      }
+   }
+
+   public static Builder builder() {
+      return new Builder();
+   }
+
+   public Builder toBuilder() {
+      return builder().fromError(this);
+   }
+
+   public static class Builder {
+
+      private String rawCode;
+      private Code code;
+      private String message;
+
+      /**
+       * @see Error#getRawCode()
+       */
+      public Builder rawCode(String rawCode) {
+         this.rawCode = rawCode;
+         return this;
+      }
+
+      /**
+       * @see Error#getCode()
+       */
+      public Builder code(Code code) {
+         this.code = code;
+         return this;
+      }
+
+      /**
+       * @see Error#getMessage()
+       */
+      public Builder message(String message) {
+         this.message = message;
+         return this;
+      }
+
+      public Error build() {
+         return new Error(rawCode, code, message);
+      }
+
+      public Builder fromError(Error in) {
+         return this.rawCode(in.rawCode).code(in.code).message(in.message);
+      }
+   }
+
+   private final String rawCode;
+   private final Code code;
+   private final String message;
+
+   protected Error(String rawCode, Code code, String message) {
+      this.rawCode = checkNotNull(rawCode, "rawCode for %s", message);
+      this.code = checkNotNull(code, "code for %s", message);
+      this.message = checkNotNull(message, "message");
+   }
+
+   /**
+    * Error code
+    */
+   public Code getCode() {
+      return code;
+   }
+
+   /**
+    * Error code, unparsed
+    */
+   public String getRawCode() {
+      return rawCode;
+   }
+
+   /**
+    * User message
+    */
+   public String getMessage() {
+      return message;
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public int hashCode() {
+      return Objects.hashCode(rawCode, code, message);
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public boolean equals(Object obj) {
+      if (this == obj)
+         return true;
+      if (obj == null)
+         return false;
+      if (getClass() != obj.getClass())
+         return false;
+      Error other = (Error) obj;
+      return Objects.equal(this.rawCode, other.rawCode) && Objects.equal(this.code, other.code)
+               && Objects.equal(this.message, other.message);
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public String toString() {
+      return Objects.toStringHelper(this).omitNullValues().add("code", rawCode).add("message", message).toString();
+   }
+
+}
diff --git a/labs/azure-management/src/main/java/org/jclouds/azure/management/domain/HostedService.java b/labs/azure-management/src/main/java/org/jclouds/azure/management/domain/HostedService.java
new file mode 100644
index 0000000..8d35271
--- /dev/null
+++ b/labs/azure-management/src/main/java/org/jclouds/azure/management/domain/HostedService.java
@@ -0,0 +1,197 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.azure.management.domain;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.net.URI;
+
+import com.google.common.base.CaseFormat;
+import com.google.common.base.Objects;
+import com.google.common.base.Objects.ToStringHelper;
+
+/**
+ * System properties for the specified hosted service
+ * 
+ * @see <a href="http://msdn.microsoft.com/en-us/library/gg441293" >api</a>
+ * @author Adrian Cole
+ */
+public class HostedService {
+   public static enum Status {
+
+      CREATING,
+
+      CREATED,
+
+      DELETING,
+
+      DELETED,
+
+      CHANGING,
+
+      RESOLVING_DNS,
+
+      UNRECOGNIZED;
+
+      public String value() {
+         return CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.UPPER_CAMEL, name());
+      }
+
+      @Override
+      public String toString() {
+         return value();
+      }
+
+      public static Status fromValue(String status) {
+         try {
+            return valueOf(CaseFormat.UPPER_CAMEL.to(CaseFormat.UPPER_UNDERSCORE, checkNotNull(status, "status")));
+         } catch (IllegalArgumentException e) {
+            return UNRECOGNIZED;
+         }
+      }
+   }
+
+   public static Builder<?> builder() {
+      return new ConcreteBuilder();
+   }
+
+   public Builder<?> toBuilder() {
+      return new ConcreteBuilder().fromHostedService(this);
+   }
+
+   public static abstract class Builder<T extends Builder<T>> {
+      protected abstract T self();
+
+      protected URI url;
+      protected String name;
+      protected HostedServiceProperties properties;
+
+      /**
+       * @see HostedService#getUrl()
+       */
+      public T url(URI url) {
+         this.url = url;
+         return self();
+      }
+
+      /**
+       * @see HostedService#getName()
+       */
+      public T name(String name) {
+         this.name = name;
+         return self();
+      }
+
+      /**
+       * @see HostedService#getProperties()
+       */
+      public T properties(HostedServiceProperties properties) {
+         this.properties = properties;
+         return self();
+      }
+
+      public HostedService build() {
+         return new HostedService(url, name, properties);
+      }
+
+      public T fromHostedService(HostedService in) {
+         return this.url(in.getUrl()).name(in.getName()).properties(in.getProperties());
+      }
+   }
+
+   private static class ConcreteBuilder extends Builder<ConcreteBuilder> {
+      @Override
+      protected ConcreteBuilder self() {
+         return this;
+      }
+   }
+
+   protected final URI url;
+   protected final String name;
+   protected final HostedServiceProperties properties;
+
+   protected HostedService(URI url, String name, HostedServiceProperties properties) {
+      this.url = checkNotNull(url, "url");
+      this.name = checkNotNull(name, "name");
+      this.properties = checkNotNull(properties, "properties");
+   }
+
+   /**
+    * The Service Management API request URI used to perform Get Hosted Service Properties requests
+    * against the hosted service.
+    */
+   public URI getUrl() {
+      return url;
+   }
+
+   /**
+    * The name of the hosted service. This name is the DNS prefix name and can be 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
+    */
+   public String getName() {
+      return name;
+   }
+
+   /**
+    * Provides the url of the database properties to be used for this DB HostedService.
+    */
+   public HostedServiceProperties getProperties() {
+      return properties;
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public int hashCode() {
+      return Objects.hashCode(url);
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public boolean equals(Object obj) {
+      if (this == obj)
+         return true;
+      if (obj == null)
+         return false;
+      if (getClass() != obj.getClass())
+         return false;
+      HostedService other = (HostedService) obj;
+      return Objects.equal(this.url, other.url);
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public String toString() {
+      return string().toString();
+   }
+
+   protected ToStringHelper string() {
+      return Objects.toStringHelper(this).omitNullValues().add("url", url).add("name", name)
+               .add("properties", properties);
+   }
+
+}
diff --git a/labs/azure-management/src/main/java/org/jclouds/azure/management/domain/HostedServiceProperties.java b/labs/azure-management/src/main/java/org/jclouds/azure/management/domain/HostedServiceProperties.java
new file mode 100644
index 0000000..d8477f7
--- /dev/null
+++ b/labs/azure-management/src/main/java/org/jclouds/azure/management/domain/HostedServiceProperties.java
@@ -0,0 +1,182 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.azure.management.domain;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import com.google.common.base.Objects;
+import com.google.common.base.Objects.ToStringHelper;
+import com.google.common.base.Optional;
+
+/**
+ * System properties for the specified hosted service. These properties include the service name and
+ * service type; the name of the affinity group to which the service belongs, or its location if it
+ * is not part of an affinity group.
+ * 
+ * @see <a href="http://msdn.microsoft.com/en-us/library/gg441293" >api</a>
+ * @author Adrian Cole
+ */
+public class HostedServiceProperties {
+   public static Builder<?> builder() {
+      return new ConcreteBuilder();
+   }
+
+   public Builder<?> toBuilder() {
+      return new ConcreteBuilder().fromHostedServiceProperties(this);
+   }
+
+   public static abstract class Builder<T extends Builder<T>> {
+      protected abstract T self();
+
+      protected Optional<String> description = Optional.absent();
+      protected Optional<String> location = Optional.absent();
+      protected Optional<String> affinityGroup = Optional.absent();
+      protected String label;
+
+      /**
+       * @see HostedServiceProperties#getDescription()
+       */
+      public T description(String description) {
+         this.description = Optional.fromNullable(description);
+         return self();
+      }
+
+      /**
+       * @see HostedServiceProperties#getLocation()
+       */
+      public T location(String location) {
+         this.location = Optional.fromNullable(location);
+         return self();
+      }
+
+      /**
+       * @see HostedServiceProperties#getAffinityGroup()
+       */
+      public T affinityGroup(String affinityGroup) {
+         this.affinityGroup = Optional.fromNullable(affinityGroup);
+         return self();
+      }
+
+      /**
+       * @see HostedServiceProperties#getLabel()
+       */
+      public T label(String label) {
+         this.label = label;
+         return self();
+      }
+
+      public HostedServiceProperties build() {
+         return new HostedServiceProperties(description, location, affinityGroup, label);
+      }
+
+      public T fromHostedServiceProperties(HostedServiceProperties in) {
+         return this.description(in.getDescription().orNull()).location(in.getLocation().orNull())
+                  .affinityGroup(in.getAffinityGroup().orNull()).label(in.getLabel());
+      }
+   }
+
+   private static class ConcreteBuilder extends Builder<ConcreteBuilder> {
+      @Override
+      protected ConcreteBuilder self() {
+         return this;
+      }
+   }
+
+   protected final Optional<String> description;
+   protected final Optional<String> location;
+   protected final Optional<String> affinityGroup;
+   protected final String label;
+
+   protected HostedServiceProperties(Optional<String> description, Optional<String> location,
+            Optional<String> affinityGroup, String label) {
+      this.description = checkNotNull(description, "description");
+      this.location = checkNotNull(location, "location");
+      this.affinityGroup = checkNotNull(affinityGroup, "affinityGroup");
+      this.label = checkNotNull(label, "label");
+   }
+
+   /**
+    * The description for the hosted service..
+    */
+   public Optional<String> getDescription() {
+      return description;
+   }
+
+   /**
+    * The geo-location of the hosted service in Windows Azure, if the hosted service is not
+    * associated with an affinity group. If a location has been specified, the AffinityGroup element
+    * is not returned.
+    */
+   public Optional<String> getLocation() {
+      return location;
+   }
+
+   /**
+    * The affinity group with which this hosted service is associated, if any. If the service is
+    * associated with an affinity group, the Location element is not returned.
+    */
+   public Optional<String> getAffinityGroup() {
+      return affinityGroup;
+   }
+
+   /**
+    *  The name can be up to 100 characters in length. The name can be used identify the storage account for your tracking purposes.
+    */
+   public String getLabel() {
+      return label;
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public int hashCode() {
+      return Objects.hashCode(description, location, affinityGroup, label);
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public boolean equals(Object obj) {
+      if (this == obj)
+         return true;
+      if (obj == null)
+         return false;
+      if (getClass() != obj.getClass())
+         return false;
+      HostedServiceProperties other = (HostedServiceProperties) obj;
+      return Objects.equal(this.description, other.description) && Objects.equal(this.location, other.location)
+               && Objects.equal(this.affinityGroup, other.affinityGroup) && Objects.equal(this.label, other.label);
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public String toString() {
+      return string().toString();
+   }
+
+   protected ToStringHelper string() {
+      return Objects.toStringHelper(this).omitNullValues().add("description", description.orNull())
+               .add("location", location.orNull()).add("affinityGroup", affinityGroup.orNull()).add("label", label);
+   }
+
+}
diff --git a/labs/azure-management/src/main/java/org/jclouds/azure/management/domain/HostedServiceWithDetailedProperties.java b/labs/azure-management/src/main/java/org/jclouds/azure/management/domain/HostedServiceWithDetailedProperties.java
new file mode 100644
index 0000000..2011e69
--- /dev/null
+++ b/labs/azure-management/src/main/java/org/jclouds/azure/management/domain/HostedServiceWithDetailedProperties.java
@@ -0,0 +1,71 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.azure.management.domain;
+
+import java.net.URI;
+
+/**
+ * 
+ * @author Adrian Cole
+ */
+public class HostedServiceWithDetailedProperties extends HostedService {
+
+   public static Builder<?> builder() {
+      return new ConcreteBuilder();
+   }
+
+   public Builder<?> toBuilder() {
+      return new ConcreteBuilder().fromHostedServiceWithDetailedProperties(this);
+   }
+
+   public static abstract class Builder<T extends Builder<T>> extends HostedService.Builder<T> {
+
+      @Override
+      public T properties(HostedServiceProperties properties) {
+         this.properties = DetailedHostedServiceProperties.class.cast(properties);
+         return self();
+      }
+
+      public HostedServiceWithDetailedProperties build() {
+         return new HostedServiceWithDetailedProperties(url, name,
+                  DetailedHostedServiceProperties.class.cast(properties));
+      }
+
+      public T fromHostedServiceWithDetailedProperties(HostedServiceWithDetailedProperties in) {
+         return fromHostedService(in);
+      }
+   }
+
+   private static class ConcreteBuilder extends Builder<ConcreteBuilder> {
+      @Override
+      protected ConcreteBuilder self() {
+         return this;
+      }
+   }
+
+   protected HostedServiceWithDetailedProperties(URI url, String serviceName, DetailedHostedServiceProperties properties) {
+      super(url, serviceName, properties);
+   }
+
+   @Override
+   public DetailedHostedServiceProperties getProperties() {
+      return DetailedHostedServiceProperties.class.cast(properties);
+   }
+
+}
diff --git a/labs/azure-management/src/main/java/org/jclouds/azure/management/domain/InputEndpoint.java b/labs/azure-management/src/main/java/org/jclouds/azure/management/domain/InputEndpoint.java
new file mode 100644
index 0000000..c3b5b29
--- /dev/null
+++ b/labs/azure-management/src/main/java/org/jclouds/azure/management/domain/InputEndpoint.java
@@ -0,0 +1,123 @@
+package org.jclouds.azure.management.domain;
+
+import org.jclouds.azure.management.domain.role.Protocol;
+
+public class InputEndpoint {
+
+	public static Builder builder() {
+		return new Builder();
+	}
+
+	public static class Builder {
+		private Integer localPort;
+		private Integer externalPort;
+		private String name;
+		private Protocol protocol;
+
+		public Builder localPort(Integer localPort) {
+			this.localPort = localPort;
+			return this;
+		}
+
+		public Builder externalPort(Integer externalPort) {
+			this.externalPort = externalPort;
+			return this;
+		}
+
+		public Builder name(String name) {
+			this.name = name;
+			return this;
+		}
+
+		public Builder protocol(Protocol protocol) {
+			this.protocol = protocol;
+			return this;
+		}
+		
+		public InputEndpoint build(){
+			return new InputEndpoint(localPort, externalPort, name, protocol);
+		}
+
+	}
+
+	private final Integer localPort;
+	private final Integer externalPort;
+	private final String name;
+	private final Protocol protocol;
+
+	public InputEndpoint(Integer localPort, Integer externalPort, String name,
+			Protocol protocol) {
+		super();
+		this.localPort = localPort;
+		this.externalPort = externalPort;
+		this.name = name;
+		this.protocol = protocol;
+	}
+
+	public Integer getLocalPort() {
+		return localPort;
+	}
+
+	public Integer getExternalPort() {
+		return externalPort;
+	}
+
+	public String getName() {
+		return name;
+	}
+
+	public Protocol getProtocol() {
+		return protocol;
+	}
+
+	@Override
+	public int hashCode() {
+		final int prime = 31;
+		int result = 1;
+		result = prime * result
+				+ ((externalPort == null) ? 0 : externalPort.hashCode());
+		result = prime * result
+				+ ((localPort == null) ? 0 : localPort.hashCode());
+		result = prime * result + ((name == null) ? 0 : name.hashCode());
+		result = prime * result
+				+ ((protocol == null) ? 0 : protocol.hashCode());
+		return result;
+	}
+
+	@Override
+	public boolean equals(Object obj) {
+		if (this == obj)
+			return true;
+		if (obj == null)
+			return false;
+		if (getClass() != obj.getClass())
+			return false;
+		InputEndpoint other = (InputEndpoint) obj;
+		if (externalPort == null) {
+			if (other.externalPort != null)
+				return false;
+		} else if (!externalPort.equals(other.externalPort))
+			return false;
+		if (localPort == null) {
+			if (other.localPort != null)
+				return false;
+		} else if (!localPort.equals(other.localPort))
+			return false;
+		if (name == null) {
+			if (other.name != null)
+				return false;
+		} else if (!name.equals(other.name))
+			return false;
+		if (protocol != other.protocol)
+			return false;
+		return true;
+	}
+
+	@Override
+	public String toString() {
+		return "InputEndPoint [localPort=" + localPort + ", externalPort="
+				+ externalPort + ", name=" + name + ", protocol=" + protocol
+				+ "]";
+	}
+
+}
diff --git a/labs/azure-management/src/main/java/org/jclouds/azure/management/domain/InstanceStatus.java b/labs/azure-management/src/main/java/org/jclouds/azure/management/domain/InstanceStatus.java
new file mode 100644
index 0000000..c375052
--- /dev/null
+++ b/labs/azure-management/src/main/java/org/jclouds/azure/management/domain/InstanceStatus.java
@@ -0,0 +1,139 @@
+package org.jclouds.azure.management.domain;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import com.google.common.base.CaseFormat;
+
+public enum InstanceStatus {
+
+	/**
+	 * The role state is currently unknown. The state should automatically be
+	 * resolved once the role state is detected, so no action is required.
+	 */
+	ROLE_STATE_UNKNOWN,
+
+	/**
+	 * The host agent is currently creating resources for the Virtual Machine
+	 * (VM).
+	 */
+	CREATING_V_M,
+
+	/**
+	 * The host agent is starting the Virtual Machine.
+	 */
+	STARTING_V_M,
+
+	/**
+	 * Windows Azure is creating resources for the role.
+	 */
+	CREATING_ROLE,
+
+	/**
+	 * Windows Azure is starting the role.
+	 */
+	STARTING_ROLE,
+
+	/**
+	 * The role instance has started and is ready to be used.
+	 */
+	READY_ROLE,
+
+	/**
+	 * The role instance is unavailable for requests. This state is usually
+	 * generated while the role is being created or stopped.
+	 */
+	BUSY_ROLE,
+
+	/**
+	 * Windows Azure is stopping the role.
+	 */
+	STOPPING_ROLE,
+
+	/**
+	 * The host agent is stopping the Virtual Machine. This status also
+	 * indicates that the role has already been stopped.
+	 */
+	STOPPING_V_M,
+
+	/**
+	 * The Virtual Machine is being deleted by the host agent.
+	 */
+	DELETING_V_M,
+
+	/**
+	 * The Virtual Machine is not running. This is the final state of the
+	 * shutdown process, and no other status messages should be received after
+	 * StoppedVM.
+	 */
+	STOPPED_V_M,
+
+	/**
+	 * The role has unexpectedly stopped or has failed to start. This status
+	 * indicates that there is a problem with the role that is causing it to
+	 * crash or preventing it from starting, and must be corrected before the
+	 * role can be started. The InstanceStateDetails and InstanceErrorCode
+	 * fields can hold information about the role error that caused this state,
+	 * which may be useful for identifying and debugging the problem.
+	 */
+	RESTARTING_ROLE,
+
+	/**
+	 * The role has continually crashed after being started by Windows Azure.
+	 * This status indicates that there is a problem with the role that prevents
+	 * it from starting, and may be generated after the StartingRole even
+	 * ReadyRole statuses are received. The problem in the role must be found
+	 * and corrected before the role can be started. The InstanceStateDetails
+	 * and InstanceErrorCode fields can hold information about the role error
+	 * that caused this state, which may be useful for identifying and debugging
+	 * the problem.
+	 */
+	CYCLING_ROLE,
+
+	/**
+	 * The role has continually failed to start. This status indicates that
+	 * there is a problem with the role that prevents it from starting, and may
+	 * be generated after the process returns StartingRole. The problem in the
+	 * role must be found and corrected before the role can be started. The
+	 * InstanceStateDetails and InstanceErrorCode fields can hold information
+	 * about the role error that caused this state, which may be useful for
+	 * identifying and debugging the problem.
+	 */
+	FAILED_STARTING_ROLE,
+
+	/**
+	 * A Windows Azure or container error is preventing the Virtual Machine from
+	 * starting. This status is generated by Windows Azure, and does not
+	 * indicate an error with the role. It may be generated after the
+	 * StartingRole state.
+	 */
+	FAILED_STARTING_V_M,
+
+	/**
+	 * The role has timed out before receiving a status message and is not
+	 * responding to requests.
+	 */
+	UNRESPONSIVE_ROLE,
+	
+	/**
+	 * UNDOCUMENTED BY AZURE
+	 */
+	PROVISIONING;
+
+	public String value() {
+		return CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.UPPER_CAMEL, name());
+	}
+
+	@Override
+	public String toString() {
+		return value();
+	}
+
+	public static InstanceStatus fromValue(String type) {
+		try {
+			return valueOf(CaseFormat.UPPER_CAMEL.to(
+					CaseFormat.UPPER_UNDERSCORE, checkNotNull(type, "type")));
+		} catch (IllegalArgumentException e) {
+			return ROLE_STATE_UNKNOWN;
+		}
+	}
+}
diff --git a/labs/azure-management/src/main/java/org/jclouds/azure/management/domain/Location.java b/labs/azure-management/src/main/java/org/jclouds/azure/management/domain/Location.java
new file mode 100644
index 0000000..47fe012
--- /dev/null
+++ b/labs/azure-management/src/main/java/org/jclouds/azure/management/domain/Location.java
@@ -0,0 +1,164 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.azure.management.domain;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.util.Set;
+
+import com.google.common.base.Objects;
+import com.google.common.collect.ImmutableSet;
+
+/**
+ * 
+ * A geographical region in which a service or storage account will be hosted.
+ * 
+ * @see <a href="http://msdn.microsoft.com/en-us/library/gg441293" >api</a>
+ * 
+ * @author Adrian Cole
+ */
+public class Location {
+   public static Builder builder() {
+      return new Builder();
+   }
+
+   public Builder toBuilder() {
+      return builder().fromLocation(this);
+   }
+
+   public static class Builder {
+
+      private String name;
+      private String displayName;
+      private ImmutableSet.Builder<String> availableServices = ImmutableSet.<String> builder();
+
+      /**
+       * @see Location#getName()
+       */
+      public Builder name(String name) {
+         this.name = name;
+         return this;
+      }
+
+      /**
+       * @see Location#getDisplayName()
+       */
+      public Builder displayName(String displayName) {
+         this.displayName = displayName;
+         return this;
+      }
+
+      /**
+       * @see Location#getAvailableServices()
+       */
+      public Builder addAvailableService(String availableService) {
+         this.availableServices.add(checkNotNull(availableService, "availableService"));
+         return this;
+      }
+
+      /**
+       * @see Location#getAvailableServices()
+       */
+      public Builder availableServices(Iterable<String> availableServices) {
+         this.availableServices = ImmutableSet.<String> builder().addAll(
+                  checkNotNull(availableServices, "availableServices"));
+         return this;
+      }
+
+      public Location build() {
+         return new Location(name, displayName, availableServices.build());
+      }
+
+      public Builder fromLocation(Location in) {
+         return this.name(in.getName()).displayName(in.getDisplayName()).availableServices(in.getAvailableServices());
+      }
+   }
+
+   private final String name;
+   private final String displayName;
+   private final Set<String> availableServices;
+
+   protected Location(String name, String displayName, Iterable<String> availableServices) {
+      this.name = checkNotNull(name, "name");
+      this.displayName = checkNotNull(displayName, "displayName for %s", name);
+      this.availableServices = ImmutableSet.copyOf(checkNotNull(availableServices, "availableServices for %s", name));
+   }
+
+   /**
+    * 
+    * The name of a data center location that is valid for your subscription. For example:
+    * {@code West Europe}
+    */
+   public String getName() {
+      return name;
+   }
+
+   /**
+    * The localized name of data center location.
+    */
+   public String getDisplayName() {
+      return displayName;
+   }
+
+   /**
+    * Indicates the services available at a location.
+    * 
+    * Returned values are none, one, or both of the values listed below.
+    * 
+    * Compute
+    * 
+    * Storage
+    */
+   public Set<String> getAvailableServices() {
+      return availableServices;
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public int hashCode() {
+      return Objects.hashCode(name);
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public boolean equals(Object obj) {
+      if (this == obj)
+         return true;
+      if (obj == null)
+         return false;
+      if (getClass() != obj.getClass())
+         return false;
+      Location other = (Location) obj;
+      return Objects.equal(this.name, other.name);
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public String toString() {
+      return Objects.toStringHelper(this).omitNullValues().add("name", name).add("displayName", displayName)
+               .add("availableServices", availableServices).toString();
+   }
+
+}
diff --git a/labs/azure-management/src/main/java/org/jclouds/azure/management/domain/OSImage.java b/labs/azure-management/src/main/java/org/jclouds/azure/management/domain/OSImage.java
new file mode 100644
index 0000000..5002533
--- /dev/null
+++ b/labs/azure-management/src/main/java/org/jclouds/azure/management/domain/OSImage.java
@@ -0,0 +1,308 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.azure.management.domain;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.net.URI;
+
+import com.google.common.base.Objects;
+import com.google.common.base.Objects.ToStringHelper;
+import com.google.common.base.Optional;
+
+/**
+ * OS images from the image repository
+ * 
+ * @see <a href="http://msdn.microsoft.com/en-us/library/jj157191" >api</a>
+ * @author Adrian Cole
+ */
+public class OSImage {
+   public static Builder<?> builder() {
+      return new ConcreteBuilder();
+   }
+
+   public Builder<?> toBuilder() {
+      return new ConcreteBuilder().fromHostedService(this);
+   }
+
+   public static abstract class Builder<T extends Builder<T>> {
+      protected abstract T self();
+
+      protected OSType os;
+      protected String name;
+      protected Optional<Integer> logicalSizeInGB = Optional.absent();
+      protected Optional<String> description = Optional.absent();
+      protected Optional<String> category = Optional.absent();
+      protected Optional<String> location = Optional.absent();
+      protected Optional<String> affinityGroup = Optional.absent();
+      protected Optional<URI> mediaLink = Optional.absent();
+      protected Optional<URI> eula = Optional.absent();
+      protected String label;
+
+      /**
+       * @see OSImage#getOS()
+       */
+      public T os(OSType os) {
+         this.os = os;
+         return self();
+      }
+
+      /**
+       * @see OSImage#getName()
+       */
+      public T name(String name) {
+         this.name = name;
+         return self();
+      }
+
+      /**
+       * @see OSImage#getDescription()
+       */
+      public T description(String description) {
+         this.description = Optional.fromNullable(description);
+         return self();
+      }
+
+      /**
+       * @see OSImage#getLogicalSizeInGB()
+       */
+      public T logicalSizeInGB(Integer logicalSizeInGB) {
+         this.logicalSizeInGB = Optional.fromNullable(logicalSizeInGB);
+         return self();
+      }
+
+      /**
+       * @see OSImage#getCategory()
+       */
+      public T category(String category) {
+         this.category = Optional.fromNullable(category);
+         return self();
+      }
+
+      /**
+       * @see OSImage#getLocation()
+       */
+      public T location(String location) {
+         this.location = Optional.fromNullable(location);
+         return self();
+      }
+
+      /**
+       * @see OSImage#getAffinityGroup()
+       */
+      public T affinityGroup(String affinityGroup) {
+         this.affinityGroup = Optional.fromNullable(affinityGroup);
+         return self();
+      }
+
+      /**
+       * @see OSImage#getMediaLink()
+       */
+      public T mediaLink(URI mediaLink) {
+         this.mediaLink = Optional.fromNullable(mediaLink);
+         return self();
+      }
+
+      /**
+       * @see OSImage#getEula()
+       */
+      public T eula(URI eula) {
+         this.eula = Optional.fromNullable(eula);
+         return self();
+      }
+
+      /**
+       * @see OSImage#getLabel()
+       */
+      public T label(String label) {
+         this.label = label;
+         return self();
+      }
+
+      public OSImage build() {
+         return new OSImage(os, name, logicalSizeInGB, description, category, location, affinityGroup, mediaLink, eula,
+                  label);
+      }
+
+      public T fromHostedService(OSImage in) {
+         return this.os(in.getOS()).name(in.getName()).logicalSizeInGB(in.getLogicalSizeInGB().orNull())
+                  .description(in.getDescription().orNull()).category(in.getCategory().orNull())
+                  .location(in.getLocation().orNull()).affinityGroup(in.getAffinityGroup().orNull())
+                  .mediaLink(in.getMediaLink().orNull()).eula(in.getEula().orNull()).label(in.getLabel());
+      }
+   }
+
+   private static class ConcreteBuilder extends Builder<ConcreteBuilder> {
+      @Override
+      protected ConcreteBuilder self() {
+         return this;
+      }
+   }
+
+   protected final OSType os;
+   protected final String name;
+   protected final Optional<Integer> logicalSizeInGB;
+   protected final Optional<String> description;
+   protected final Optional<String> category;
+   protected final Optional<String> location;
+   protected final Optional<String> affinityGroup;
+   protected final Optional<URI> mediaLink;
+   protected final Optional<URI> eula;
+   protected final String label;
+
+   protected OSImage(OSType os, String name, Optional<Integer> logicalSizeInGB, Optional<String> description,
+            Optional<String> category, Optional<String> location, Optional<String> affinityGroup,
+            Optional<URI> mediaLink, Optional<URI> eula, String label) {
+      this.name = checkNotNull(name, "name");
+      this.logicalSizeInGB = checkNotNull(logicalSizeInGB, "logicalSizeInGB for %s", name);
+      this.description = checkNotNull(description, "description for %s", name);
+      this.os = checkNotNull(os, "os for %s", name);
+      this.category = checkNotNull(category, "category for %s", name);
+      this.location = checkNotNull(location, "location for %s", name);
+      this.affinityGroup = checkNotNull(affinityGroup, "affinityGroup for %s", name);
+      this.mediaLink = checkNotNull(mediaLink, "mediaLink for %s", name);
+      this.eula = checkNotNull(eula, "eula for %s", name);
+      this.label = checkNotNull(label, "label for %s", name);
+   }
+
+   /**
+    * The operating system type of the OS image.
+    */
+   public OSType getOS() {
+      return os;
+   }
+
+   /**
+    * The name of the hosted service. This name is the DNS prefix name and can be 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
+    */
+   public String getName() {
+      return name;
+   }
+
+   /**
+    * The size, in GB, of the image.
+    */
+   public Optional<Integer> getLogicalSizeInGB() {
+      return logicalSizeInGB;
+   }
+
+   /**
+    * The description for the image.
+    */
+   public Optional<String> getDescription() {
+      return description;
+   }
+
+   /**
+    * The repository classification of image. All user images have the category "User", but
+    * categories for other images could be, for example "Canonical"
+    */
+   public Optional<String> getCategory() {
+      return category;
+   }
+
+   /**
+    * The geo-location in which this media is located. The Location value is derived from storage
+    * account that contains the blob in which the media is located. If the storage account belongs
+    * to an affinity group the value is absent.
+    */
+   public Optional<String> getLocation() {
+      return location;
+   }
+
+   /**
+    * The affinity in which the media is located. The AffinityGroup value is derived from storage
+    * account that contains the blob in which the media is located. If the storage account does not
+    * belong to an affinity group the value is absent.
+    */
+   public Optional<String> getAffinityGroup() {
+      return affinityGroup;
+   }
+
+   /**
+    * The location of the blob in the blob store in which the media for the image is located. The
+    * blob location belongs to a storage account in the subscription specified by the
+    * <subscription-id> value in the operation call.
+    * 
+    * Example:
+    * 
+    * http://example.blob.core.windows.net/disks/myimage.vhd
+    */
+   public Optional<URI> getMediaLink() {
+      return mediaLink;
+   }
+
+   /**
+    * The eula for the image, if available.
+    */
+   public Optional<URI> getEula() {
+      return eula;
+   }
+
+   /**
+    * The description of the image.
+    */
+   public String getLabel() {
+      return label;
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public int hashCode() {
+      return Objects.hashCode(name);
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public boolean equals(Object obj) {
+      if (this == obj)
+         return true;
+      if (obj == null)
+         return false;
+      if (getClass() != obj.getClass())
+         return false;
+      OSImage other = (OSImage) obj;
+      return Objects.equal(this.name, other.name);
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public String toString() {
+      return string().toString();
+   }
+
+   protected ToStringHelper string() {
+      return Objects.toStringHelper(this).omitNullValues().add("os", os).add("name", name)
+               .add("logicalSizeInGB", logicalSizeInGB.orNull()).add("description", description)
+               .add("category", category.orNull()).add("location", location.orNull())
+               .add("affinityGroup", affinityGroup.orNull()).add("mediaLink", mediaLink.orNull())
+               .add("eula", eula.orNull()).add("label", label);
+   }
+
+}
diff --git a/labs/azure-management/src/main/java/org/jclouds/azure/management/domain/OSImageParams.java b/labs/azure-management/src/main/java/org/jclouds/azure/management/domain/OSImageParams.java
new file mode 100644
index 0000000..6c42dc6
--- /dev/null
+++ b/labs/azure-management/src/main/java/org/jclouds/azure/management/domain/OSImageParams.java
@@ -0,0 +1,179 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.azure.management.domain;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.net.URI;
+
+import com.google.common.base.Objects;
+import com.google.common.base.Objects.ToStringHelper;
+
+/**
+ * The Add OS Image operation adds an OS image that is currently stored in a storage account in your
+ * subscription to the image repository.
+ * 
+ * @see <a href="http://msdn.microsoft.com/en-us/library/jj157191" >api</a>
+ * @author Adrian Cole
+ */
+public class OSImageParams {
+
+   public static Builder builder() {
+      return new Builder();
+   }
+
+   public Builder toBuilder() {
+      return builder().fromHostedService(this);
+   }
+
+   public static class Builder {
+
+      protected String label;
+      protected URI mediaLink;
+      protected OSType os;
+      protected String name;
+
+      /**
+       * @see OSImageParams#getLabel()
+       */
+      public Builder label(String label) {
+         this.label = label;
+         return this;
+      }
+
+      /**
+       * @see OSImageParams#getMediaLink()
+       */
+      public Builder mediaLink(URI mediaLink) {
+         this.mediaLink = mediaLink;
+         return this;
+      }
+
+      /**
+       * @see OSImageParams#getName()
+       */
+      public Builder name(String name) {
+         this.name = name;
+         return this;
+      }
+
+      /**
+       * @see OSImageParams#getOS()
+       */
+      public Builder os(OSType os) {
+         this.os = os;
+         return this;
+      }
+
+      public OSImageParams build() {
+         return new OSImageParams(label, mediaLink, name, os);
+      }
+
+      public Builder fromHostedService(OSImageParams in) {
+         return this.label(in.getLabel()).mediaLink(in.getMediaLink()).name(in.getName()).os(in.getOS());
+      }
+   }
+
+   protected final String label;
+   protected final URI mediaLink;
+   protected final String name;
+   protected final OSType os;
+
+   protected OSImageParams(String label, URI mediaLink, String name, OSType os) {
+      this.label = checkNotNull(label, "label");
+      this.name = checkNotNull(name, "name for %s", label);
+      this.mediaLink = checkNotNull(mediaLink, "mediaLink for %s", label);
+      this.os = checkNotNull(os, "os for %s", label);
+   }
+
+   /**
+    * The operating system type of the OS image.
+    */
+   public OSType getOS() {
+      return os;
+   }
+
+   /**
+    * The name of the hosted service. This name is the DNS prefix name and can be 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
+    */
+   public String getName() {
+      return name;
+   }
+
+   /**
+    * The location of the blob in the blob store in which the media for the image is located. The
+    * blob location belongs to a storage account in the subscription specified by the
+    * <subscription-id> value in the operation call.
+    * 
+    * Example:
+    * 
+    * http://example.blob.core.windows.net/disks/myimage.vhd
+    */
+   public URI getMediaLink() {
+      return mediaLink;
+   }
+
+   /**
+    * The description of the image.
+    */
+   public String getLabel() {
+      return label;
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public int hashCode() {
+      return Objects.hashCode(name);
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public boolean equals(Object obj) {
+      if (this == obj)
+         return true;
+      if (obj == null)
+         return false;
+      if (getClass() != obj.getClass())
+         return false;
+      OSImageParams other = (OSImageParams) obj;
+      return Objects.equal(this.name, other.name);
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public String toString() {
+      return string().toString();
+   }
+
+   protected ToStringHelper string() {
+      return Objects.toStringHelper(this).add("label", label).add("mediaLink", mediaLink).add("name", name)
+               .add("os", os);
+   }
+
+}
diff --git a/labs/azure-management/src/main/java/org/jclouds/azure/management/domain/OSType.java b/labs/azure-management/src/main/java/org/jclouds/azure/management/domain/OSType.java
new file mode 100644
index 0000000..8764f39
--- /dev/null
+++ b/labs/azure-management/src/main/java/org/jclouds/azure/management/domain/OSType.java
@@ -0,0 +1,49 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.azure.management.domain;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import com.google.common.base.CaseFormat;
+
+public enum OSType {
+
+   LINUX,
+
+   WINDOWS,
+
+   UNRECOGNIZED;
+
+   public String value() {
+      return CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.UPPER_CAMEL, name());
+   }
+
+   @Override
+   public String toString() {
+      return value();
+   }
+
+   public static OSType fromValue(String type) {
+      try {
+         return valueOf(CaseFormat.UPPER_CAMEL.to(CaseFormat.UPPER_UNDERSCORE, checkNotNull(type, "type")));
+      } catch (IllegalArgumentException e) {
+         return UNRECOGNIZED;
+      }
+   }
+}
\ No newline at end of file
diff --git a/labs/azure-management/src/main/java/org/jclouds/azure/management/domain/Operation.java b/labs/azure-management/src/main/java/org/jclouds/azure/management/domain/Operation.java
new file mode 100644
index 0000000..c0d4a04
--- /dev/null
+++ b/labs/azure-management/src/main/java/org/jclouds/azure/management/domain/Operation.java
@@ -0,0 +1,213 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.azure.management.domain;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import com.google.common.base.CaseFormat;
+import com.google.common.base.Objects;
+import com.google.common.base.Optional;
+
+/**
+ * 
+ * Determines whether the operation has succeeded, failed, or is still in progress.
+ * 
+ * @see <a href="http://msdn.microsoft.com/en-us/library/ee460783" >api</a>
+ * 
+ * @author Adrian Cole
+ */
+public class Operation {
+
+   public static enum Status {
+
+      IN_PROGRESS,
+
+      SUCCEEDED,
+
+      FAILED,
+
+      UNRECOGNIZED;
+
+      public String value() {
+         return CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.UPPER_CAMEL, name());
+      }
+
+      @Override
+      public String toString() {
+         return value();
+      }
+
+      public static Status fromValue(String status) {
+         try {
+            return valueOf(CaseFormat.UPPER_CAMEL.to(CaseFormat.UPPER_UNDERSCORE, checkNotNull(status, "status")));
+         } catch (IllegalArgumentException e) {
+            return UNRECOGNIZED;
+         }
+      }
+   }
+
+   public static Builder builder() {
+      return new Builder();
+   }
+
+   public Builder toBuilder() {
+      return builder().fromOperation(this);
+   }
+
+   public static class Builder {
+
+      private String id;
+      private String rawStatus;
+      private Status status;
+      // When the operation is in progress, no status code is returned
+      private Optional<Integer> httpStatusCode = Optional.absent();
+      private Optional<Error> error = Optional.absent();
+
+      /**
+       * @see Operation#getId()
+       */
+      public Builder id(String id) {
+         this.id = id;
+         return this;
+      }
+
+      /**
+       * @see Operation#getRawStatus()
+       */
+      public Builder rawStatus(String rawStatus) {
+         this.rawStatus = rawStatus;
+         return this;
+      }
+
+      /**
+       * @see Operation#getStatus()
+       */
+      public Builder status(Status status) {
+         this.status = status;
+         return this;
+      }
+
+      /**
+       * @see Operation#getHttpStatusCode()
+       */
+      public Builder httpStatusCode(Integer httpStatusCode) {
+         this.httpStatusCode = Optional.fromNullable(httpStatusCode);;
+         return this;
+      }
+
+      /**
+       * @see Operation#getError()
+       */
+      public Builder error(Error error) {
+         this.error = Optional.fromNullable(error);
+         return this;
+      }
+
+      public Operation build() {
+         return new Operation(id, rawStatus, status, httpStatusCode, error);
+      }
+
+      public Builder fromOperation(Operation in) {
+         return this.id(in.id).rawStatus(in.rawStatus).status(in.status).httpStatusCode(in.httpStatusCode.orNull())
+                  .error(in.error.orNull());
+      }
+   }
+
+   private final String id;
+   private final String rawStatus;
+   private final Status status;
+   private final Optional<Integer> httpStatusCode;
+   private final Optional<Error> error;
+
+   protected Operation(String id, String rawStatus, Status status, Optional<Integer> httpStatusCode, Optional<Error> error) {
+      this.id = checkNotNull(id, "id");
+      this.rawStatus = checkNotNull(rawStatus, "rawStatus for %s", id);
+      this.status = checkNotNull(status, "status for %s", id);
+      this.httpStatusCode = checkNotNull(httpStatusCode, "httpStatusCode for %s", id);;
+      this.error = checkNotNull(error, "error for %s", id);
+   }
+
+   /**
+    * The request ID of the asynchronous request.
+    */
+   public String getId() {
+      return id;
+   }
+
+   /**
+    * The status of the asynchronous request.
+    */
+   public Status getStatus() {
+      return status;
+   }
+
+   /**
+    * The status of the asynchronous request, unparsed
+    */
+   public String getRawStatus() {
+      return rawStatus;
+   }
+
+   /**
+    * The HTTP status code for the asynchronous request.
+    */
+   public Optional<Integer> getHttpStatusCode() {
+      return httpStatusCode;
+   }
+
+   /**
+    * The management service error returned if the asynchronous request failed.
+    */
+   public Optional<Error> getError() {
+      return error;
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public int hashCode() {
+      return Objects.hashCode(id);
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public boolean equals(Object obj) {
+      if (this == obj)
+         return true;
+      if (obj == null)
+         return false;
+      if (getClass() != obj.getClass())
+         return false;
+      Operation other = (Operation) obj;
+      return Objects.equal(this.id, other.id);
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public String toString() {
+      return Objects.toStringHelper(this).omitNullValues().add("id", id).add("status", rawStatus)
+               .add("httpStatusCode", httpStatusCode).add("error", error.orNull()).toString();
+   }
+
+}
diff --git a/labs/azure-management/src/main/java/org/jclouds/azure/management/domain/RoleSize.java b/labs/azure-management/src/main/java/org/jclouds/azure/management/domain/RoleSize.java
new file mode 100644
index 0000000..21400d0
--- /dev/null
+++ b/labs/azure-management/src/main/java/org/jclouds/azure/management/domain/RoleSize.java
@@ -0,0 +1,27 @@
+package org.jclouds.azure.management.domain;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import com.google.common.base.CaseFormat;
+
+public enum RoleSize {
+	EXTRA_SMALL, SMALL, MEDIUM, LARGE, EXTRA_LARGE;
+
+	public String value() {
+		return CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.UPPER_CAMEL, name());
+	}
+
+	@Override
+	public String toString() {
+		return value();
+	}
+
+	public static RoleSize fromValue(String type) {
+		try {
+			return valueOf(CaseFormat.UPPER_CAMEL.to(
+					CaseFormat.UPPER_UNDERSCORE, checkNotNull(type, "type")));
+		} catch (IllegalArgumentException e) {
+			return null;
+		}
+	}
+}
diff --git a/labs/azure-management/src/main/java/org/jclouds/azure/management/domain/hostedservice/CreateDeployment.java b/labs/azure-management/src/main/java/org/jclouds/azure/management/domain/hostedservice/CreateDeployment.java
new file mode 100644
index 0000000..d815617
--- /dev/null
+++ b/labs/azure-management/src/main/java/org/jclouds/azure/management/domain/hostedservice/CreateDeployment.java
@@ -0,0 +1,197 @@
+package org.jclouds.azure.management.domain.hostedservice;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlElementWrapper;
+import javax.xml.bind.annotation.XmlRootElement;
+
+@XmlRootElement(name = "CreateDeployment")
+public class CreateDeployment {
+
+   /**
+    * The name for the deployment. The deployment name must be unique among other deployments for
+    * the hosted service.
+    */
+   @XmlElement(required = true, name = "Name")
+   private String name;
+
+   /**
+    * A URL that refers to the location of the service package in the Blob service. The service
+    * package can be located either in a storage account beneath the same subscription or a Shared
+    * Access Signature (SAS) URI from any storage account.
+    */
+   @XmlElement(required = true, name = "PackageUrl")
+   private String packageUrl;
+
+   /**
+    * The base-64 encoded service configuration file for the deployment.
+    */
+   @XmlElement(required = true, name = "Configuration")
+   private String configuration;
+
+   /**
+    * A name for the hosted service that is base-64 encoded. The name can be up to 100 characters in
+    * length.
+    * 
+    * It is recommended that the label be unique within the subscription. The name can be used
+    * identify the hosted service for your tracking purposes.
+    */
+   @XmlElement(required = true, name = "Label")
+   private String label;
+
+   /**
+    * 
+    * Indicates whether to start the deployment immediately after it is created. The default value
+    * is false.
+    * 
+    * If false, the service model is still deployed to the virtual machines but the code is not run
+    * immediately. Instead, the service is Suspended until you call Update Deployment Status and set
+    * the status to Running, at which time the service will be started. A deployed service still
+    * incurs charges, even if it is suspended.
+    */
+   @XmlElement(name = "StartDeployment")
+   private Boolean startDeployment;
+
+   /**
+    * 
+    * Optional. Indicates whether to treat package validation warnings as errors. The default value
+    * is false. If set to true, the Created Deployment operation fails if there are validation
+    * warnings on the service package.
+    */
+   @XmlElement(name = "TreatWarningsAsError")
+   private Boolean treatWarningsAsError;
+
+   @XmlElementWrapper(name = "ExtendedProperties")
+   @XmlElement(required = true, name = "ExtendedProperty")
+   private List<ExtendedProperty> extendedProperties = new ArrayList<ExtendedProperty>();
+
+   public CreateDeployment() {
+   }
+
+   public String getName() {
+      return name;
+   }
+
+   public void setName(String name) {
+      this.name = name;
+   }
+
+   public String getPackageUrl() {
+      return packageUrl;
+   }
+
+   public void setPackageUrl(String packageUrl) {
+      this.packageUrl = packageUrl;
+   }
+
+   public String getConfiguration() {
+      return configuration;
+   }
+
+   public void setConfiguration(String configuration) {
+      this.configuration = configuration;
+   }
+
+   public String getLabel() {
+      return label;
+   }
+
+   public void setLabel(String label) {
+      this.label = label;
+   }
+
+   public Boolean getStartDeployment() {
+      return startDeployment;
+   }
+
+   public void setStartDeployment(Boolean startDeployment) {
+      this.startDeployment = startDeployment;
+   }
+
+   public Boolean getTreatWarningsAsError() {
+      return treatWarningsAsError;
+   }
+
+   public void setTreatWarningsAsError(Boolean treatWarningsAsError) {
+      this.treatWarningsAsError = treatWarningsAsError;
+   }
+
+   public List<ExtendedProperty> getExtendedProperties() {
+      return extendedProperties;
+   }
+
+   public void setExtendedProperties(List<ExtendedProperty> extendedProperties) {
+      this.extendedProperties = extendedProperties;
+   }
+
+   @Override
+   public int hashCode() {
+      final int prime = 31;
+      int result = 1;
+      result = prime * result + ((configuration == null) ? 0 : configuration.hashCode());
+      result = prime * result + ((extendedProperties == null) ? 0 : extendedProperties.hashCode());
+      result = prime * result + ((label == null) ? 0 : label.hashCode());
+      result = prime * result + ((name == null) ? 0 : name.hashCode());
+      result = prime * result + ((packageUrl == null) ? 0 : packageUrl.hashCode());
+      result = prime * result + ((startDeployment == null) ? 0 : startDeployment.hashCode());
+      result = prime * result + ((treatWarningsAsError == null) ? 0 : treatWarningsAsError.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;
+      CreateDeployment other = (CreateDeployment) obj;
+      if (configuration == null) {
+         if (other.configuration != null)
+            return false;
+      } else if (!configuration.equals(other.configuration))
+         return false;
+      if (extendedProperties == null) {
+         if (other.extendedProperties != null)
+            return false;
+      } else if (!extendedProperties.equals(other.extendedProperties))
+         return false;
+      if (label == null) {
+         if (other.label != null)
+            return false;
+      } else if (!label.equals(other.label))
+         return false;
+      if (name == null) {
+         if (other.name != null)
+            return false;
+      } else if (!name.equals(other.name))
+         return false;
+      if (packageUrl == null) {
+         if (other.packageUrl != null)
+            return false;
+      } else if (!packageUrl.equals(other.packageUrl))
+         return false;
+      if (startDeployment == null) {
+         if (other.startDeployment != null)
+            return false;
+      } else if (!startDeployment.equals(other.startDeployment))
+         return false;
+      if (treatWarningsAsError == null) {
+         if (other.treatWarningsAsError != null)
+            return false;
+      } else if (!treatWarningsAsError.equals(other.treatWarningsAsError))
+         return false;
+      return true;
+   }
+
+   @Override
+   public String toString() {
+      return "CreateDeployment [name=" + name + ", packageUrl=" + packageUrl + ", configuration=" + configuration
+               + ", label=" + label + ", startDeployment=" + startDeployment + ", treatWarningsAsError="
+               + treatWarningsAsError + ", extendedProperties=" + extendedProperties + "]";
+   }
+
+}
diff --git a/labs/azure-management/src/main/java/org/jclouds/azure/management/domain/hostedservice/ExtendedProperty.java b/labs/azure-management/src/main/java/org/jclouds/azure/management/domain/hostedservice/ExtendedProperty.java
new file mode 100644
index 0000000..ad13d71
--- /dev/null
+++ b/labs/azure-management/src/main/java/org/jclouds/azure/management/domain/hostedservice/ExtendedProperty.java
@@ -0,0 +1,86 @@
+package org.jclouds.azure.management.domain.hostedservice;
+
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+
+@XmlRootElement(name = "ExtendedProperty")
+public class ExtendedProperty {
+
+   /**
+    * 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. Attempting to use
+    * other characters, starting the Name with a non-letter character, or entering a name that is
+    * identical to that of another extended property owned by the same hosted service, will result
+    * in a status code 400 (Bad Request) error.
+    */
+   @XmlElement(name = "Name")
+   private String name;
+
+   /**
+    * Represents the value 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, and each extended property value has a maximum length of 255 characters.
+    */
+   @XmlElement(name = "Value")
+   private String value;
+
+   public ExtendedProperty() {
+   }
+
+   public String getName() {
+      return name;
+   }
+
+   public void setName(String name) {
+      this.name = name;
+   }
+
+   public String getValue() {
+      return value;
+   }
+
+   public void setValue(String value) {
+      this.value = value;
+   }
+
+   @Override
+   public int hashCode() {
+      final int prime = 31;
+      int result = 1;
+      result = prime * result + ((name == null) ? 0 : name.hashCode());
+      result = prime * result + ((value == null) ? 0 : value.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;
+      ExtendedProperty other = (ExtendedProperty) obj;
+      if (name == null) {
+         if (other.name != null)
+            return false;
+      } else if (!name.equals(other.name))
+         return false;
+      if (value == null) {
+         if (other.value != null)
+            return false;
+      } else if (!value.equals(other.value))
+         return false;
+      return true;
+   }
+
+   @Override
+   public String toString() {
+      return "ExtendedProperty [name=" + name + ", value=" + value + "]";
+   }
+
+}
diff --git a/labs/azure-management/src/main/java/org/jclouds/azure/management/domain/hostedservice/package-info.java b/labs/azure-management/src/main/java/org/jclouds/azure/management/domain/hostedservice/package-info.java
new file mode 100644
index 0000000..157ed36
--- /dev/null
+++ b/labs/azure-management/src/main/java/org/jclouds/azure/management/domain/hostedservice/package-info.java
@@ -0,0 +1,26 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+@XmlSchema(namespace = "http://schemas.microsoft.com/windowsazure", elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED)
+@XmlAccessorType(XmlAccessType.FIELD)
+package org.jclouds.azure.management.domain.hostedservice;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlSchema;
+
diff --git a/labs/azure-management/src/main/java/org/jclouds/azure/management/domain/role/AbstractRole.java b/labs/azure-management/src/main/java/org/jclouds/azure/management/domain/role/AbstractRole.java
new file mode 100644
index 0000000..71ec6ce
--- /dev/null
+++ b/labs/azure-management/src/main/java/org/jclouds/azure/management/domain/role/AbstractRole.java
@@ -0,0 +1,126 @@
+package org.jclouds.azure.management.domain.role;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlElementWrapper;
+
+import org.jclouds.azure.management.domain.role.conf.ConfigurationSet;
+
+//@XmlRootElement(name = "PersistentVMRole")
+public abstract class AbstractRole {
+
+   /**
+    * Specifies the name for the virtual machine. The name must be unique within Windows Azure.
+    */
+   @XmlElement(required = true, name = "RoleName")
+   private String roleName;
+
+   /**
+    * The type of the role for the virtual machine. The only supported value is PersistentVMRole.
+    */
+   @XmlElement(required = true, name = "RoleType")
+   private String roleType;
+
+   /**
+    * Required. You must specifye either a WindowsProvisioningConfigurationSet or
+    * LinuxProvisioningConfigurationSet configuration set.
+    * 
+    * Optional. You can specify a NetworkConfigurationSet which contains the metadata required to
+    * create the virtual network configuration for a virtual machine.
+    */
+   @XmlElementWrapper(name = "ConfigurationSets")
+   @XmlElement(name = "ConfigurationSet")
+   private List<ConfigurationSet> configurationSets = new ArrayList<ConfigurationSet>(0);
+   
+   /**
+    * Specifies the name of an availability set to which to add the virtual machine. This value
+    * controls the virtual machine allocation in the Windows Azure environment. Virtual machines
+    * specified in the same availability set are allocated to different nodes to maximize
+    * availability.
+    */
+   @XmlElement(name = "AvailabilitySetName")
+   private String availabilitySetName;
+
+   @XmlElementWrapper(name = "DataVirtualHardDisks")
+   @XmlElement(name = "DataVirtualHardDisk")
+   private List<DataVirtualHardDisk> dataVirtualHardDisks = new ArrayList<DataVirtualHardDisk>(0);
+   
+   @XmlElement(name = "OSVirtualHardDisk")
+   private OSVirtualHardDisk osVirtualHardDisk;
+   
+   /**
+    * The size of the virtual machine to allocate. The default value is Small.
+    */
+   @XmlElement(name = "RoleSize")
+   private RoleSize roleSize;
+
+   public AbstractRole() {
+      super();
+   }
+
+   public String getRoleName() {
+      return roleName;
+   }
+
+   public String getRoleType() {
+      return roleType;
+   }
+
+   public String getAvailabilitySetName() {
+      return availabilitySetName;
+   }
+
+   public RoleSize getRoleSize() {
+      return roleSize;
+   }
+
+   public void setRoleName(String roleName) {
+      this.roleName = roleName;
+   }
+
+   public void setRoleType(String roleType) {
+      this.roleType = roleType;
+   }
+
+   public void setAvailabilitySetName(String availabilitySetName) {
+      this.availabilitySetName = availabilitySetName;
+   }
+
+   public void setRoleSize(RoleSize roleSize) {
+      this.roleSize = roleSize;
+   }
+
+   public void setOsVirtualHardDisk(OSVirtualHardDisk osVirtualHardDisk) {
+      this.osVirtualHardDisk = osVirtualHardDisk;
+   }
+
+   public OSVirtualHardDisk getOsVirtualHardDisk() {
+      return osVirtualHardDisk;
+   }
+
+   public List<? extends ConfigurationSet> getConfigurationSets() {
+      return configurationSets;
+   }
+
+   public void setConfigurationSets(List<ConfigurationSet> configurationSets) {
+      this.configurationSets = configurationSets;
+   }
+
+   public List<DataVirtualHardDisk> getDataVirtualHardDisks() {
+      return dataVirtualHardDisks;
+   }
+
+   public void setDataVirtualHardDisks(List<DataVirtualHardDisk> dataVirtualHardDisks) {
+      this.dataVirtualHardDisks = dataVirtualHardDisks;
+   }
+
+   @Override
+   public String toString() {
+      return "Role [roleName=" + roleName + ", roleType=" + roleType + ", availabilitySetName=" + availabilitySetName
+               + ", roleSize=" + roleSize + ", osVirtualHardDisk=" + osVirtualHardDisk + ", configurationSets="
+               + configurationSets + ", dataVirtualHardDisks=" + dataVirtualHardDisks + "]";
+   }
+
+}
diff --git a/labs/azure-management/src/main/java/org/jclouds/azure/management/domain/role/DNS.java b/labs/azure-management/src/main/java/org/jclouds/azure/management/domain/role/DNS.java
new file mode 100644
index 0000000..767a8c3
--- /dev/null
+++ b/labs/azure-management/src/main/java/org/jclouds/azure/management/domain/role/DNS.java
@@ -0,0 +1,61 @@
+package org.jclouds.azure.management.domain.role;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlElementWrapper;
+import javax.xml.bind.annotation.XmlRootElement;
+
+@XmlRootElement(name = "Dns")
+public class DNS {
+   /**
+    * Contains the parameters specifying the DNS servers to use for the virtual machine.
+    */
+   @XmlElementWrapper(required = true, name = "DnsServers")
+   @XmlElement(name = "DnsServer")
+   private List<DNSServer> dnsServers = new ArrayList<DNSServer>();
+
+   public DNS() {
+      super();
+   }
+
+   public List<DNSServer> getDnsServers() {
+      return dnsServers;
+   }
+
+   public void setDnsServers(List<DNSServer> dnsServers) {
+      this.dnsServers = dnsServers;
+   }
+
+   @Override
+   public int hashCode() {
+      final int prime = 31;
+      int result = 1;
+      result = prime * result + ((dnsServers == null) ? 0 : dnsServers.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;
+      DNS other = (DNS) obj;
+      if (dnsServers == null) {
+         if (other.dnsServers != null)
+            return false;
+      } else if (!dnsServers.equals(other.dnsServers))
+         return false;
+      return true;
+   }
+
+   @Override
+   public String toString() {
+      return "DNS [dnsServers=" + dnsServers + "]";
+   }
+
+}
diff --git a/labs/azure-management/src/main/java/org/jclouds/azure/management/domain/role/DNSServer.java b/labs/azure-management/src/main/java/org/jclouds/azure/management/domain/role/DNSServer.java
new file mode 100644
index 0000000..d65dd49
--- /dev/null
+++ b/labs/azure-management/src/main/java/org/jclouds/azure/management/domain/role/DNSServer.java
@@ -0,0 +1,77 @@
+package org.jclouds.azure.management.domain.role;
+
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+
+@XmlRootElement(name = "DnsServer")
+public class DNSServer {
+
+   /**
+    * Specifies the name of the DNS server.
+    */
+   @XmlElement(required = true, name = "Name")
+   private String name;
+
+   /**
+    * Specifies the IP address of the DNS server.
+    */
+   @XmlElement(required = true, name = "Address")
+   private String address;
+
+   public DNSServer() {
+      super();
+   }
+
+   public String getName() {
+      return name;
+   }
+
+   public void setName(String name) {
+      this.name = name;
+   }
+
+   public String getAddress() {
+      return address;
+   }
+
+   public void setAddress(String address) {
+      this.address = address;
+   }
+
+   @Override
+   public int hashCode() {
+      final int prime = 31;
+      int result = 1;
+      result = prime * result + ((address == null) ? 0 : address.hashCode());
+      result = prime * result + ((name == null) ? 0 : name.hashCode());
+      return result;
+   }
+
+   @Override
+   public boolean equals(Object obj) {
+      if (this == obj)
+         return true;
+      if (obj == null)
+         return false;
+      if (getClass() != obj.getClass())
+         return false;
+      DNSServer other = (DNSServer) obj;
+      if (address == null) {
+         if (other.address != null)
+            return false;
+      } else if (!address.equals(other.address))
+         return false;
+      if (name == null) {
+         if (other.name != null)
+            return false;
+      } else if (!name.equals(other.name))
+         return false;
+      return true;
+   }
+
+   @Override
+   public String toString() {
+      return "DNSServer [name=" + name + ", address=" + address + "]";
+   }
+
+}
diff --git a/labs/azure-management/src/main/java/org/jclouds/azure/management/domain/role/DataVirtualHardDisk.java b/labs/azure-management/src/main/java/org/jclouds/azure/management/domain/role/DataVirtualHardDisk.java
new file mode 100644
index 0000000..333992f
--- /dev/null
+++ b/labs/azure-management/src/main/java/org/jclouds/azure/management/domain/role/DataVirtualHardDisk.java
@@ -0,0 +1,41 @@
+package org.jclouds.azure.management.domain.role;
+
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+
+@XmlRootElement(name = "DataVirtualHardDisk")
+public class DataVirtualHardDisk extends VirtualHardDisk {
+
+   @XmlElement(name = "Lun")
+   private Integer lun;
+
+   @XmlElement(name = "LogicalDiskSizeInGB")
+   private Integer logicalDiskSizeInGB;
+
+   public DataVirtualHardDisk() {
+
+   }
+
+   public Integer getLun() {
+      return lun;
+   }
+
+   public void setLun(Integer lun) {
+      this.lun = lun;
+   }
+
+   public Integer getLogicalDiskSizeInGB() {
+      return logicalDiskSizeInGB;
+   }
+
+   public void setLogicalDiskSizeInGB(Integer logicalDiskSizeInGB) {
+      this.logicalDiskSizeInGB = logicalDiskSizeInGB;
+   }
+
+   @Override
+   public String toString() {
+      return "DataVirtualHardDisk [lun=" + lun + ", logicalDiskSizeInGB=" + logicalDiskSizeInGB + ", hostCaching="
+               + hostCaching + ", diskLabel=" + diskLabel + ", diskName=" + diskName + ", mediaLink=" + mediaLink + "]";
+   }
+
+}
diff --git a/labs/azure-management/src/main/java/org/jclouds/azure/management/domain/role/Deployment.java b/labs/azure-management/src/main/java/org/jclouds/azure/management/domain/role/Deployment.java
new file mode 100644
index 0000000..99e8e64
--- /dev/null
+++ b/labs/azure-management/src/main/java/org/jclouds/azure/management/domain/role/Deployment.java
@@ -0,0 +1,168 @@
+package org.jclouds.azure.management.domain.role;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlElementWrapper;
+import javax.xml.bind.annotation.XmlRootElement;
+
+@XmlRootElement(name = "Deployment")
+public class Deployment {
+
+   /**
+    * A name for the deployment. The deployment name must be unique among other deployments for the
+    * hosted service.
+    */
+   @XmlElement(required = true, name = "Name")
+   private String name;
+
+   /**
+    * Specifies the environment in which to deploy the virtual machine.
+    * 
+    * Possible values are: Staging Production
+    */
+   @XmlElement(required = true, name = "DeploymentSlot")
+   private String deploymentSlot;
+
+   /**
+    * A name for the hosted service that is base-64 encoded. The name can be up to 100 characters in
+    * length.
+    * 
+    * It is recommended that the label be unique within the subscription. The name can be used
+    * identify the hosted service for tracking purposes.
+    */
+   @XmlElement(required = true, name = "Label")
+   private String label;
+
+   @XmlElementWrapper(required = true, name = "RoleList")
+   @XmlElement(required = true, name = "Role")
+   private List<Role> roleList = new ArrayList<Role>();
+
+   /**
+    * Specifies the name of an existing virtual network to which the deployment will belong.
+    * 
+    * Virtual networks are created by calling the Set Network Configuration operation.
+    */
+   @XmlElement(required = true, name = "VirtualNetworkName")
+   private String virtualNetworkName;
+
+   /**
+    * Contains a list of DNS servers to associate with the machine.
+    */
+   @XmlElement(required = true, name = "Dns")
+   private DNS dns;
+
+   public Deployment() {
+   }
+
+   public String getName() {
+      return name;
+   }
+
+   public void setName(String name) {
+      this.name = name;
+   }
+
+   public String getDeploymentSlot() {
+      return deploymentSlot;
+   }
+
+   public void setDeploymentSlot(String deploymentSlot) {
+      this.deploymentSlot = deploymentSlot;
+   }
+
+   public String getLabel() {
+      return label;
+   }
+
+   public void setLabel(String label) {
+      this.label = label;
+   }
+
+   public List<Role> getRoleList() {
+      return roleList;
+   }
+
+   public void setRoleList(List<Role> roleList) {
+      this.roleList = roleList;
+   }
+
+   public String getVirtualNetworkName() {
+      return virtualNetworkName;
+   }
+
+   public void setVirtualNetworkName(String virtualNetworkName) {
+      this.virtualNetworkName = virtualNetworkName;
+   }
+
+   public DNS getDns() {
+      return dns;
+   }
+
+   public void setDns(DNS dns) {
+      this.dns = dns;
+   }
+
+   @Override
+   public int hashCode() {
+      final int prime = 31;
+      int result = 1;
+      result = prime * result + ((deploymentSlot == null) ? 0 : deploymentSlot.hashCode());
+      result = prime * result + ((dns == null) ? 0 : dns.hashCode());
+      result = prime * result + ((label == null) ? 0 : label.hashCode());
+      result = prime * result + ((name == null) ? 0 : name.hashCode());
+      result = prime * result + ((roleList == null) ? 0 : roleList.hashCode());
+      result = prime * result + ((virtualNetworkName == null) ? 0 : virtualNetworkName.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 (deploymentSlot == null) {
+         if (other.deploymentSlot != null)
+            return false;
+      } else if (!deploymentSlot.equals(other.deploymentSlot))
+         return false;
+      if (dns == null) {
+         if (other.dns != null)
+            return false;
+      } else if (!dns.equals(other.dns))
+         return false;
+      if (label == null) {
+         if (other.label != null)
+            return false;
+      } else if (!label.equals(other.label))
+         return false;
+      if (name == null) {
+         if (other.name != null)
+            return false;
+      } else if (!name.equals(other.name))
+         return false;
+      if (roleList == null) {
+         if (other.roleList != null)
+            return false;
+      } else if (!roleList.equals(other.roleList))
+         return false;
+      if (virtualNetworkName == null) {
+         if (other.virtualNetworkName != null)
+            return false;
+      } else if (!virtualNetworkName.equals(other.virtualNetworkName))
+         return false;
+      return true;
+   }
+
+   @Override
+   public String toString() {
+      return "Deployment [name=" + name + ", deploymentSlot=" + deploymentSlot + ", label=" + label + ", roleList="
+               + roleList + ", virtualNetworkName=" + virtualNetworkName + ", dns=" + dns + "]";
+   }
+
+}
diff --git a/labs/azure-management/src/main/java/org/jclouds/azure/management/domain/role/HostCaching.java b/labs/azure-management/src/main/java/org/jclouds/azure/management/domain/role/HostCaching.java
new file mode 100644
index 0000000..0cb9cfa
--- /dev/null
+++ b/labs/azure-management/src/main/java/org/jclouds/azure/management/domain/role/HostCaching.java
@@ -0,0 +1,13 @@
+package org.jclouds.azure.management.domain.role;
+
+import javax.xml.bind.annotation.XmlEnum;
+import javax.xml.bind.annotation.XmlEnumValue;
+import javax.xml.bind.annotation.XmlType;
+
+@XmlType(name = "HostCaching")
+@XmlEnum
+public enum HostCaching {
+   @XmlEnumValue("ReadOnly")
+   ReadOnly, @XmlEnumValue("ReadWrite")
+   ReadWrite;
+}
diff --git a/labs/azure-management/src/main/java/org/jclouds/azure/management/domain/role/OSVirtualHardDisk.java b/labs/azure-management/src/main/java/org/jclouds/azure/management/domain/role/OSVirtualHardDisk.java
new file mode 100644
index 0000000..96eb9e7
--- /dev/null
+++ b/labs/azure-management/src/main/java/org/jclouds/azure/management/domain/role/OSVirtualHardDisk.java
@@ -0,0 +1,53 @@
+package org.jclouds.azure.management.domain.role;
+
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+
+/**
+ * Contains the parameters Windows Azure uses to create the operating system
+ * disk for the virtual machine.
+ * 
+ * @author gpereira
+ * 
+ */
+@XmlRootElement(name = "OSVirtualHardDisk")
+public class OSVirtualHardDisk extends VirtualHardDisk {
+
+	/**
+	 * Specifies the name of the disk image to use to create the virtual
+	 * machine.
+	 */
+	@XmlElement(name = "SourceImageName")
+	private String sourceImageName;
+
+	@XmlElement(name = "OS")
+	private String os;
+
+	public OSVirtualHardDisk() {
+
+	}
+
+	public String getSourceImageName() {
+		return sourceImageName;
+	}
+
+	public void setSourceImageName(String sourceImageName) {
+		this.sourceImageName = sourceImageName;
+	}
+
+	public void setOs(String os) {
+		this.os = os;
+	}
+
+	public String getOs() {
+		return os;
+	}
+
+	@Override
+	public String toString() {
+		return "OSVirtualHardDisk [hostCaching=" + hostCaching + ", diskLabel="
+				+ diskLabel + ", diskName=" + diskName + ", mediaLink="
+				+ mediaLink + ", sourceImageName=" + sourceImageName + "]";
+	}
+
+}
diff --git a/labs/azure-management/src/main/java/org/jclouds/azure/management/domain/role/PersistentVMRole.java b/labs/azure-management/src/main/java/org/jclouds/azure/management/domain/role/PersistentVMRole.java
new file mode 100644
index 0000000..94ff8e1
--- /dev/null
+++ b/labs/azure-management/src/main/java/org/jclouds/azure/management/domain/role/PersistentVMRole.java
@@ -0,0 +1,8 @@
+package org.jclouds.azure.management.domain.role;
+
+import javax.xml.bind.annotation.XmlRootElement;
+
+@XmlRootElement(name = "PersistentVMRole")
+public class PersistentVMRole extends AbstractRole {
+
+}
diff --git a/labs/azure-management/src/main/java/org/jclouds/azure/management/domain/role/Protocol.java b/labs/azure-management/src/main/java/org/jclouds/azure/management/domain/role/Protocol.java
new file mode 100644
index 0000000..a7cba7a
--- /dev/null
+++ b/labs/azure-management/src/main/java/org/jclouds/azure/management/domain/role/Protocol.java
@@ -0,0 +1,15 @@
+package org.jclouds.azure.management.domain.role;
+
+import javax.xml.bind.annotation.XmlEnum;
+import javax.xml.bind.annotation.XmlEnumValue;
+import javax.xml.bind.annotation.XmlType;
+
+@XmlType(name = "Protocol")
+@XmlEnum
+public enum Protocol {
+   @XmlEnumValue("tcp")
+   TCP, @XmlEnumValue("http")
+   HTTP, @XmlEnumValue("udp")
+   UDP;
+
+}
diff --git a/labs/azure-management/src/main/java/org/jclouds/azure/management/domain/role/Role.java b/labs/azure-management/src/main/java/org/jclouds/azure/management/domain/role/Role.java
new file mode 100644
index 0000000..5cec3d0
--- /dev/null
+++ b/labs/azure-management/src/main/java/org/jclouds/azure/management/domain/role/Role.java
@@ -0,0 +1,8 @@
+package org.jclouds.azure.management.domain.role;
+
+import javax.xml.bind.annotation.XmlRootElement;
+
+@XmlRootElement(name = "Role")
+public class Role extends AbstractRole {
+
+}
diff --git a/labs/azure-management/src/main/java/org/jclouds/azure/management/domain/role/RoleSize.java b/labs/azure-management/src/main/java/org/jclouds/azure/management/domain/role/RoleSize.java
new file mode 100644
index 0000000..c56b70f
--- /dev/null
+++ b/labs/azure-management/src/main/java/org/jclouds/azure/management/domain/role/RoleSize.java
@@ -0,0 +1,20 @@
+package org.jclouds.azure.management.domain.role;
+
+import javax.xml.bind.annotation.XmlEnum;
+import javax.xml.bind.annotation.XmlEnumValue;
+import javax.xml.bind.annotation.XmlType;
+
+@XmlType(name = "RoleSize")
+@XmlEnum
+public enum RoleSize {
+   @XmlEnumValue("ExtraSmall")
+   ExtraSmall, 
+   @XmlEnumValue("Small")
+   Small, 
+   @XmlEnumValue("Medium")
+   Medium, 
+   @XmlEnumValue("Large")
+   Large, 
+   @XmlEnumValue("ExtraLarge")
+   ExtraLarge;
+}
diff --git a/labs/azure-management/src/main/java/org/jclouds/azure/management/domain/role/VirtualHardDisk.java b/labs/azure-management/src/main/java/org/jclouds/azure/management/domain/role/VirtualHardDisk.java
new file mode 100644
index 0000000..0787088
--- /dev/null
+++ b/labs/azure-management/src/main/java/org/jclouds/azure/management/domain/role/VirtualHardDisk.java
@@ -0,0 +1,72 @@
+package org.jclouds.azure.management.domain.role;
+
+import javax.xml.bind.annotation.XmlElement;
+
+public class VirtualHardDisk {
+
+   /**
+    * Specifies whether the OS disk can be cached for greater efficiency during writes. This setting
+    * impacts the consistency and performance of the OS disk. The default value is ReadWrite.
+    */
+   @XmlElement(name = "HostCaching")
+   protected HostCaching hostCaching;
+   /**
+    * Specifies the friendly name of the disk containing the guest OS image in the image repository.
+    */
+   @XmlElement(name = "DiskLabel")
+   protected String diskLabel;
+   /**
+    * Specifies the name of an operating system image in the image repository.
+    */
+   @XmlElement(name = "DiskName")
+   protected String diskName;
+   /**
+    * Specifies the URI for a blob in a Windows Azure storage account that contains the OS image to
+    * use to create the OS disk.
+    */
+   @XmlElement(name = "MediaLink")
+   protected String mediaLink;
+
+   public VirtualHardDisk() {
+
+   }
+
+   public HostCaching getHostCaching() {
+      return hostCaching;
+   }
+
+   public void setHostCaching(HostCaching hostCaching) {
+      this.hostCaching = hostCaching;
+   }
+
+   public String getDiskLabel() {
+      return diskLabel;
+   }
+
+   public void setDiskLabel(String diskLabel) {
+      this.diskLabel = diskLabel;
+   }
+
+   public String getDiskName() {
+      return diskName;
+   }
+
+   public void setDiskName(String diskName) {
+      this.diskName = diskName;
+   }
+
+   public String getMediaLink() {
+      return mediaLink;
+   }
+
+   public void setMediaLink(String mediaLink) {
+      this.mediaLink = mediaLink;
+   }
+
+   @Override
+   public String toString() {
+      return "VirtualHardDisk [hostCaching=" + hostCaching + ", diskLabel=" + diskLabel + ", diskName=" + diskName
+               + ", mediaLink=" + mediaLink + "]";
+   }
+
+}
diff --git a/labs/azure-management/src/main/java/org/jclouds/azure/management/domain/role/conf/CertificateSetting.java b/labs/azure-management/src/main/java/org/jclouds/azure/management/domain/role/conf/CertificateSetting.java
new file mode 100644
index 0000000..150b6c1
--- /dev/null
+++ b/labs/azure-management/src/main/java/org/jclouds/azure/management/domain/role/conf/CertificateSetting.java
@@ -0,0 +1,62 @@
+package org.jclouds.azure.management.domain.role.conf;
+
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+
+@XmlRootElement(name = "CertificateSetting")
+public class CertificateSetting {
+
+   /**
+    * Specifies the name of the certificate store from which retrieve certificate.
+    */
+   @XmlElement(required = true, name = "StoreLocation")
+   private String StoreLocation;
+   /**
+    * Specifies the target certificate store location on the virtual machine.
+    * 
+    * The only supported value is LocalMachine.
+    */
+   @XmlElement(required = true, name = "StoreName")
+   private String StoreName;
+   /**
+    * Specifies the thumbprint of the certificate to be provisioned. The thumbprint must specify an
+    * existing service certificate.
+    */
+   @XmlElement(required = true, name = "Thumbprint")
+   private String Thumbprint;
+
+   public CertificateSetting() {
+      super();
+   }
+
+   public String getStoreLocation() {
+      return StoreLocation;
+   }
+
+   public void setStoreLocation(String storeLocation) {
+      StoreLocation = storeLocation;
+   }
+
+   public String getStoreName() {
+      return StoreName;
+   }
+
+   public void setStoreName(String storeName) {
+      StoreName = storeName;
+   }
+
+   public String getThumbprint() {
+      return Thumbprint;
+   }
+
+   public void setThumbprint(String thumbprint) {
+      Thumbprint = thumbprint;
+   }
+
+   @Override
+   public String toString() {
+      return "CertificateSetting [StoreLocation=" + StoreLocation + ", StoreName=" + StoreName + ", Thumbprint="
+               + Thumbprint + "]";
+   }
+
+}
diff --git a/labs/azure-management/src/main/java/org/jclouds/azure/management/domain/role/conf/ConfigurationSet.java b/labs/azure-management/src/main/java/org/jclouds/azure/management/domain/role/conf/ConfigurationSet.java
new file mode 100644
index 0000000..911d4ab
--- /dev/null
+++ b/labs/azure-management/src/main/java/org/jclouds/azure/management/domain/role/conf/ConfigurationSet.java
@@ -0,0 +1,31 @@
+package org.jclouds.azure.management.domain.role.conf;
+
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
+
+@XmlJavaTypeAdapter(ConfigurationSetAdapter.class)
+public abstract class ConfigurationSet {
+
+   /**
+    * Specifies the configuration set type.
+    */
+   @XmlElement(required = true, name = "ConfigurationSetType")
+   protected String configurationSetType;
+
+   public ConfigurationSet() {
+   }
+
+   public String getConfigurationSetType() {
+      return configurationSetType;
+   }
+
+   public void setConfigurationSetType(String configurationSetType) {
+      this.configurationSetType = configurationSetType;
+   }
+
+   @Override
+   public String toString() {
+      return "ConfigurationSet [configurationSetType=" + configurationSetType + "]";
+   }
+
+}
diff --git a/labs/azure-management/src/main/java/org/jclouds/azure/management/domain/role/conf/ConfigurationSetAdapter.java b/labs/azure-management/src/main/java/org/jclouds/azure/management/domain/role/conf/ConfigurationSetAdapter.java
new file mode 100644
index 0000000..2d3b5f8
--- /dev/null
+++ b/labs/azure-management/src/main/java/org/jclouds/azure/management/domain/role/conf/ConfigurationSetAdapter.java
@@ -0,0 +1,133 @@
+package org.jclouds.azure.management.domain.role.conf;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.TimeZone;
+
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlElementWrapper;
+import javax.xml.bind.annotation.adapters.XmlAdapter;
+
+public class ConfigurationSetAdapter extends
+         XmlAdapter<ConfigurationSetAdapter.AdaptedConfigurationSet, ConfigurationSet> {
+
+   @Override
+   public ConfigurationSet unmarshal(AdaptedConfigurationSet adapted) throws Exception {
+
+      final String type = adapted.configurationSetType;
+      if (NetworkConfiguration.ID.equals(type)) {
+         NetworkConfiguration network = new NetworkConfiguration();
+         network.setConfigurationSetType(NetworkConfiguration.ID);
+         network.setInputEndpoints(adapted.inputEndpoints);
+         network.setSubnetNames(adapted.subnetNames);
+         return network;
+      } else if (LinuxProvisioningConfiguration.ID.equals(type)) {
+         LinuxProvisioningConfiguration linux = new LinuxProvisioningConfiguration();
+         linux.setConfigurationSetType(LinuxProvisioningConfiguration.ID);
+         linux.setDisableSshPasswordAuthentication(adapted.disableSshPasswordAuthentication);
+         linux.setHostName(adapted.hostName);
+         linux.setSsh(adapted.ssh);
+         linux.setUserName(adapted.userName);
+         linux.setUserPassword(adapted.userPassword);
+         return linux;
+      } else if (WindowsProvisioningConfiguration.ID.equals(type)) {
+         WindowsProvisioningConfiguration windows = new WindowsProvisioningConfiguration();
+         windows.setConfigurationSetType(WindowsProvisioningConfiguration.ID);
+         windows.setAdminPassword(adapted.adminPassword);
+         windows.setComputerName(adapted.computerName);
+         windows.setDomainJoin(adapted.domainJoin);
+         windows.setEnableAutomaticUpdates(adapted.enableAutomaticUpdates);
+         windows.setResetPasswordOnFirstLogon(adapted.resetPasswordOnFirstLogon);
+         windows.setStoredCertificateSettings(adapted.storedCertificateSettings);
+         windows.setTimeZone(adapted.timeZone);
+         return windows;
+      }
+
+      return null;
+   }
+
+   @Override
+   public AdaptedConfigurationSet marshal(ConfigurationSet configSet) throws Exception {
+      if (configSet == null) {
+         return null;
+      }
+
+      AdaptedConfigurationSet adapted = new AdaptedConfigurationSet();
+      adapted.configurationSetType = configSet.getConfigurationSetType();
+
+      if (configSet instanceof NetworkConfiguration) {
+         NetworkConfiguration network = (NetworkConfiguration) configSet;
+         adapted.inputEndpoints = network.getInputEndpoints();
+         adapted.subnetNames = network.getSubnetNames();
+      } else if (configSet instanceof LinuxProvisioningConfiguration) {
+         LinuxProvisioningConfiguration linux = (LinuxProvisioningConfiguration) configSet;
+         adapted.disableSshPasswordAuthentication = linux.getDisableSshPasswordAuthentication();
+         adapted.hostName = linux.getHostName();
+         adapted.ssh = linux.getSsh();
+         adapted.userName = linux.getUserName();
+         adapted.userPassword = linux.getUserPassword();
+      } else if (configSet instanceof WindowsProvisioningConfiguration) {
+         WindowsProvisioningConfiguration windows = (WindowsProvisioningConfiguration) configSet;
+         adapted.adminPassword = windows.getAdminPassword();
+         adapted.computerName = windows.getComputerName();
+         adapted.domainJoin = windows.getDomainJoin();
+         adapted.enableAutomaticUpdates = windows.getEnableAutomaticUpdates();
+         adapted.resetPasswordOnFirstLogon = windows.getResetPasswordOnFirstLogon();
+         adapted.storedCertificateSettings = windows.getStoredCertificateSettings();
+         adapted.timeZone = windows.getTimeZone();
+      }
+
+      return adapted;
+   }
+
+   public static class AdaptedConfigurationSet {
+      @XmlElement(required = true, name = "ConfigurationSetType")
+      public String configurationSetType;
+
+      @XmlElement(required = true, name = "HostName")
+      public String hostName;
+
+      @XmlElement(required = true, name = "UserName")
+      public String userName;
+
+      @XmlElement(required = true, name = "UserPassword")
+      public String userPassword;
+
+      @XmlElement(name = "DisableSshPasswordAuthentication")
+      public Boolean disableSshPasswordAuthentication;
+
+      @XmlElement(name = "SSH")
+      public SSH ssh;
+
+      @XmlElement(name = "ComputerName")
+      public String computerName;
+
+      @XmlElement(required = true, name = "AdminPassword")
+      public String adminPassword;
+
+      @XmlElement(required = true, name = "ResetPasswordOnFirstLogon")
+      public Boolean resetPasswordOnFirstLogon;
+
+      @XmlElement(name = "EnableAutomaticUpdates")
+      public Boolean enableAutomaticUpdates;
+
+      @XmlElement(name = "TimeZone")
+      public TimeZone timeZone;
+
+      @XmlElement(name = "DomainJoin")
+      public DomainJoin domainJoin;
+
+      @XmlElementWrapper(required = true, name = "StoredCertificateSettings")
+      @XmlElement(name = "CertificateSetting")
+      public List<CertificateSetting> storedCertificateSettings = new ArrayList<CertificateSetting>();
+
+      @XmlElementWrapper(name = "InputEndpoints")
+      @XmlElement(name = "InputEndpoint")
+      public List<InputEndpoint> inputEndpoints = new ArrayList<InputEndpoint>(0);
+
+      @XmlElementWrapper(name = "SubnetNames")
+      @XmlElement(name = "SubnetName")
+      public List<String> subnetNames = new ArrayList<String>(0);
+   }
+
+}
diff --git a/labs/azure-management/src/main/java/org/jclouds/azure/management/domain/role/conf/Credentials.java b/labs/azure-management/src/main/java/org/jclouds/azure/management/domain/role/conf/Credentials.java
new file mode 100644
index 0000000..b229f23
--- /dev/null
+++ b/labs/azure-management/src/main/java/org/jclouds/azure/management/domain/role/conf/Credentials.java
@@ -0,0 +1,59 @@
+package org.jclouds.azure.management.domain.role.conf;
+
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+
+@XmlRootElement(name = "Credentials")
+public class Credentials {
+
+   /**
+    * Specifies the name of the domain used to authenticate an account. The value is a fully
+    * qualified DNS domain.
+    */
+   @XmlElement(name = "Domain")
+   private String domain;
+   /**
+    * Specifies a user name in the domain that can be used to join the domain.
+    */
+   @XmlElement(required = true, name = "Username")
+   private String username;
+   /**
+    * Specifies the password to use to join the domain.
+    */
+   @XmlElement(name = "Password")
+   private String password;
+
+   public Credentials() {
+      super();
+   }
+
+   public String getDomain() {
+      return domain;
+   }
+
+   public void setDomain(String domain) {
+      this.domain = domain;
+   }
+
+   public String getUsername() {
+      return username;
+   }
+
+   public void setUsername(String username) {
+      this.username = username;
+   }
+
+   public String getPassword() {
+      return password;
+   }
+
+   public void setPassword(String password) {
+      this.password = password;
+   }
+
+   @Override
+   public String toString() {
+      return "Credentials [domain=" + domain + ", username=" + username + ", password=" + password + "]";
+   }
+
+}
diff --git a/labs/azure-management/src/main/java/org/jclouds/azure/management/domain/role/conf/DomainJoin.java b/labs/azure-management/src/main/java/org/jclouds/azure/management/domain/role/conf/DomainJoin.java
new file mode 100644
index 0000000..fd9a7f0
--- /dev/null
+++ b/labs/azure-management/src/main/java/org/jclouds/azure/management/domain/role/conf/DomainJoin.java
@@ -0,0 +1,62 @@
+package org.jclouds.azure.management.domain.role.conf;
+
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+
+@XmlRootElement(name = "DomainJoin")
+public class DomainJoin {
+
+   /**
+    * Specifies the domain to join.
+    */
+   @XmlElement(name = "JoinDomain")
+   private String joinDomain;
+   /**
+    * Specifies the Lightweight Directory Access Protocol (LDAP) X 500-distinguished name of the
+    * organizational unit (OU) in which the computer account is created. This account is in Active
+    * Directory on a domain controller in the domain to which the computer is being joined.
+    */
+   @XmlElement(name = "MachineObjectOU")
+   private String machineObjectOU;
+   /**
+    * Specifies the Domain, Password, and Username values to use to join the virtual machine to the
+    * domain.
+    */
+   @XmlElement(name = "Credentials")
+   private Credentials credentials;
+
+   public DomainJoin() {
+      super();
+   }
+
+   public String getJoinDomain() {
+      return joinDomain;
+   }
+
+   public void setJoinDomain(String joinDomain) {
+      this.joinDomain = joinDomain;
+   }
+
+   public String getMachineObjectOU() {
+      return machineObjectOU;
+   }
+
+   public void setMachineObjectOU(String machineObjectOU) {
+      this.machineObjectOU = machineObjectOU;
+   }
+
+   public Credentials getCredentials() {
+      return credentials;
+   }
+
+   public void setCredentials(Credentials credentials) {
+      this.credentials = credentials;
+   }
+
+   @Override
+   public String toString() {
+      return "DomainJoin [joinDomain=" + joinDomain + ", machineObjectOU=" + machineObjectOU + ", credentials="
+               + credentials + "]";
+   }
+
+}
diff --git a/labs/azure-management/src/main/java/org/jclouds/azure/management/domain/role/conf/InputEndpoint.java b/labs/azure-management/src/main/java/org/jclouds/azure/management/domain/role/conf/InputEndpoint.java
new file mode 100644
index 0000000..ea68589
--- /dev/null
+++ b/labs/azure-management/src/main/java/org/jclouds/azure/management/domain/role/conf/InputEndpoint.java
@@ -0,0 +1,125 @@
+package org.jclouds.azure.management.domain.role.conf;
+
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+
+import org.jclouds.azure.management.domain.role.Protocol;
+
+@XmlRootElement(name = "InputEndpoint")
+public class InputEndpoint {
+
+   /**
+	 * 
+	 */
+   @XmlElement(name = "EnableDirectServerReturn")
+   private Boolean enableDirectServerReturn;
+
+   /**
+    * Specifies a name for a set of load-balanced endpoints. Specifying this element for a given
+    * endpoint adds it to the set.
+    */
+   @XmlElement(required = true, name = "LoadBalancedEndpointSetName")
+   private String loadBalancedEndpointSetName;
+
+   /**
+    * Specifies the internal port on which the virtual machine is listening to serve the endpoint.
+    */
+   @XmlElement(required = true, name = "LocalPort")
+   private Integer localPort;
+
+   /**
+    * Specifies the name for the external endpoint.
+    */
+   @XmlElement(required = true, name = "Name")
+   private String name;
+
+   /**
+    * Specifies the external port to use for the endpoint.
+    */
+   @XmlElement(required = true, name = "Port")
+   private Integer port;
+
+   @XmlElement(name = "LoadBalancerProbe")
+   private LoadBalancerProbe loadBalancerProbe;
+
+   @XmlElement(name = "Protocol")
+   private Protocol protocol;
+
+   @XmlElement(name = "Vip")
+   private String vip;
+
+   public InputEndpoint() {
+   }
+
+   public Boolean getEnableDirectServerReturn() {
+      return enableDirectServerReturn;
+   }
+
+   public void setEnableDirectServerReturn(Boolean enableDirectServerReturn) {
+      this.enableDirectServerReturn = enableDirectServerReturn;
+   }
+
+   public String getLoadBalancedEndpointSetName() {
+      return loadBalancedEndpointSetName;
+   }
+
+   public void setLoadBalancedEndpointSetName(String loadBalancedEndpointSetName) {
+      this.loadBalancedEndpointSetName = loadBalancedEndpointSetName;
+   }
+
+   public Integer getLocalPort() {
+      return localPort;
+   }
+
+   public void setLocalPort(Integer localPort) {
+      this.localPort = localPort;
+   }
+
+   public String getName() {
+      return name;
+   }
+
+   public void setName(String name) {
+      this.name = name;
+   }
+
+   public Integer getPort() {
+      return port;
+   }
+
+   public void setPort(Integer port) {
+      this.port = port;
+   }
+
+   public LoadBalancerProbe getLoadBalancerProbe() {
+      return loadBalancerProbe;
+   }
+
+   public void setLoadBalancerProbe(LoadBalancerProbe loadBalancerProbe) {
+      this.loadBalancerProbe = loadBalancerProbe;
+   }
+
+   public Protocol getProtocol() {
+      return protocol;
+   }
+
+   public void setProtocol(Protocol protocol) {
+      this.protocol = protocol;
+   }
+
+   public String getVip() {
+      return vip;
+   }
+
+   public void setVip(String vip) {
+      this.vip = vip;
+   }
+
+   @Override
+   public String toString() {
+      return "InputEndpoint [enableDirectServerReturn=" + enableDirectServerReturn + ", loadBalancedEndpointSetName="
+               + loadBalancedEndpointSetName + ", localPort=" + localPort + ", name=" + name + ", port=" + port
+               + ", loadBalancerProbe=" + loadBalancerProbe + ", protocol=" + protocol + ", vip=" + vip + "]";
+   }
+
+}
diff --git a/labs/azure-management/src/main/java/org/jclouds/azure/management/domain/role/conf/KeyPair.java b/labs/azure-management/src/main/java/org/jclouds/azure/management/domain/role/conf/KeyPair.java
new file mode 100644
index 0000000..319b82e
--- /dev/null
+++ b/labs/azure-management/src/main/java/org/jclouds/azure/management/domain/role/conf/KeyPair.java
@@ -0,0 +1,16 @@
+package org.jclouds.azure.management.domain.role.conf;
+
+import javax.xml.bind.annotation.XmlRootElement;
+
+@XmlRootElement(name = "KeyPair")
+public class KeyPair extends SSHKey {
+
+   public KeyPair() {
+   }
+
+   @Override
+   public String toString() {
+      return "KeyPair [fingerPrint=" + fingerPrint + ", path=" + path + "]";
+   }
+
+}
diff --git a/labs/azure-management/src/main/java/org/jclouds/azure/management/domain/role/conf/LinuxProvisioningConfiguration.java b/labs/azure-management/src/main/java/org/jclouds/azure/management/domain/role/conf/LinuxProvisioningConfiguration.java
new file mode 100644
index 0000000..ac54f20
--- /dev/null
+++ b/labs/azure-management/src/main/java/org/jclouds/azure/management/domain/role/conf/LinuxProvisioningConfiguration.java
@@ -0,0 +1,89 @@
+package org.jclouds.azure.management.domain.role.conf;
+
+
+public class LinuxProvisioningConfiguration extends ConfigurationSet {
+
+   public final static String ID = "LinuxProvisioningConfiguration";
+
+   /**
+    * Specifies the host name for the VM. Host names are ASCII character strings 1 to 64 characters
+    * in length.
+    */
+   // @XmlElement(required = true,name = "HostName")
+   private String hostName;
+   /**
+    * 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.
+    */
+   // @XmlElement(required = true,name = "UserName")
+   private String userName;
+   /**
+    * Specifies the associated password for the user name. PasswoazureManagement are ASCII character
+    * strings 6 to 72 characters in length.
+    */
+   // @XmlElement(required = true,name = "UserPassword")
+   private String userPassword;
+   /**
+    * Specifies whether or not SSH password authentication is disabled. By default this value is set
+    * to true.
+    */
+   // @XmlElement(name = "DisableSshPasswordAuthentication")
+   private Boolean disableSshPasswordAuthentication;
+   /**
+    * Specifies the SSH public keys and key pairs to populate in the image during provisioning.
+    */
+   // @XmlElement(name = "SSH")
+   private SSH ssh;
+
+   public LinuxProvisioningConfiguration() {
+
+   }
+
+   public String getHostName() {
+      return hostName;
+   }
+
+   public void setHostName(String hostName) {
+      this.hostName = hostName;
+   }
+
+   public String getUserName() {
+      return userName;
+   }
+
+   public void setUserName(String userName) {
+      this.userName = userName;
+   }
+
+   public String getUserPassword() {
+      return userPassword;
+   }
+
+   public void setUserPassword(String userPassword) {
+      this.userPassword = userPassword;
+   }
+
+   public Boolean getDisableSshPasswordAuthentication() {
+      return disableSshPasswordAuthentication;
+   }
+
+   public void setDisableSshPasswordAuthentication(Boolean disableSshPasswordAuthentication) {
+      this.disableSshPasswordAuthentication = disableSshPasswordAuthentication;
+   }
+
+   public SSH getSsh() {
+      return ssh;
+   }
+
+   public void setSsh(SSH ssh) {
+      this.ssh = ssh;
+   }
+
+   @Override
+   public String toString() {
+      return "LinuxProvisioningConfigurationSet [hostName=" + hostName + ", userName=" + userName + ", userPassword="
+               + userPassword + ", disableSshPasswordAuthentication=" + disableSshPasswordAuthentication + ", ssh="
+               + ssh + "]";
+   }
+
+}
diff --git a/labs/azure-management/src/main/java/org/jclouds/azure/management/domain/role/conf/LoadBalancerProbe.java b/labs/azure-management/src/main/java/org/jclouds/azure/management/domain/role/conf/LoadBalancerProbe.java
new file mode 100644
index 0000000..f7cb194
--- /dev/null
+++ b/labs/azure-management/src/main/java/org/jclouds/azure/management/domain/role/conf/LoadBalancerProbe.java
@@ -0,0 +1,68 @@
+package org.jclouds.azure.management.domain.role.conf;
+
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+
+import org.jclouds.azure.management.domain.role.Protocol;
+
+/**
+ * Contains properties that specify the endpoint settings which the Windows Azure load balancer uses
+ * to monitor the availability of this virtual machine before forwarding traffic to the endpoint.
+ * 
+ * @author gpereira
+ * 
+ */
+@XmlRootElement(name = "LoadBalancerProbe")
+public class LoadBalancerProbe {
+
+   /**
+    * Specifies the relative path name to inspect to determine the virtual machine availability
+    * status. If Protocol is set to TCP, this value must be NULL.
+    */
+   @XmlElement(name = "Path")
+   private String path;
+   /**
+    * Specifies the port to use to inspect the virtual machine availability status.
+    */
+   @XmlElement(name = "Port")
+   private Integer port;
+   /**
+    * Specifies the protocol to use to inspect the virtual machine availability status.
+    */
+   @XmlElement(name = "Protocol")
+   private Protocol protocol;
+
+   public LoadBalancerProbe() {
+      super();
+   }
+
+   public String getPath() {
+      return path;
+   }
+
+   public void setPath(String path) {
+      this.path = path;
+   }
+
+   public Integer getPort() {
+      return port;
+   }
+
+   public void setPort(Integer port) {
+      this.port = port;
+   }
+
+   public Protocol getProtocol() {
+      return protocol;
+   }
+
+   public void setProtocol(Protocol protocol) {
+      this.protocol = protocol;
+   }
+
+   @Override
+   public String toString() {
+      return "LoadBalancerProbe [path=" + path + ", port=" + port + ", protocol=" + protocol + "]";
+   }
+
+}
diff --git a/labs/azure-management/src/main/java/org/jclouds/azure/management/domain/role/conf/NetworkConfiguration.java b/labs/azure-management/src/main/java/org/jclouds/azure/management/domain/role/conf/NetworkConfiguration.java
new file mode 100644
index 0000000..6836796
--- /dev/null
+++ b/labs/azure-management/src/main/java/org/jclouds/azure/management/domain/role/conf/NetworkConfiguration.java
@@ -0,0 +1,51 @@
+package org.jclouds.azure.management.domain.role.conf;
+
+import java.util.ArrayList;
+import java.util.List;
+
+//@XmlRootElement(name = "ConfigurationSet")
+public class NetworkConfiguration extends ConfigurationSet {
+
+   public final static String ID = "NetworkConfiguration";
+
+   /**
+    * Contains a collection of external endpoints for the virtual machine.
+    */
+   // @XmlElementWrapper(name = "InputEndpoints")
+   // @XmlElement(name = "InputEndpoint")
+   private List<InputEndpoint> inputEndpoints = new ArrayList<InputEndpoint>(0);
+
+   /**
+    * Specifies the name of a subnet to which the virtual machine belongs.
+    */
+   // @XmlElementWrapper(name = "SubnetNames")
+   // @XmlElement(name = "SubnetName")
+   private List<String> subnetNames = new ArrayList<String>(0);
+
+   public NetworkConfiguration() {
+      setConfigurationSetType(ID);
+   }
+
+   public List<InputEndpoint> getInputEndpoints() {
+      return inputEndpoints;
+   }
+
+   public void setInputEndpoints(List<InputEndpoint> inputEndpoints) {
+      this.inputEndpoints = inputEndpoints;
+   }
+
+   public List<String> getSubnetNames() {
+      return subnetNames;
+   }
+
+   public void setSubnetNames(List<String> subnetNames) {
+      this.subnetNames = subnetNames;
+   }
+
+   @Override
+   public String toString() {
+      return "NetworkConfigurationSet [configurationSetType=" + configurationSetType + ", InputEndpoints="
+               + inputEndpoints + ", SubnetNames=" + subnetNames + "]";
+   }
+
+}
diff --git a/labs/azure-management/src/main/java/org/jclouds/azure/management/domain/role/conf/PublicKey.java b/labs/azure-management/src/main/java/org/jclouds/azure/management/domain/role/conf/PublicKey.java
new file mode 100644
index 0000000..0a49e91
--- /dev/null
+++ b/labs/azure-management/src/main/java/org/jclouds/azure/management/domain/role/conf/PublicKey.java
@@ -0,0 +1,16 @@
+package org.jclouds.azure.management.domain.role.conf;
+
+import javax.xml.bind.annotation.XmlRootElement;
+
+@XmlRootElement(name = "PublicKey")
+public class PublicKey extends SSHKey {
+
+   public PublicKey() {
+   }
+
+   @Override
+   public String toString() {
+      return "PublicKey [fingerPrint=" + fingerPrint + ", path=" + path + "]";
+   }
+
+}
diff --git a/labs/azure-management/src/main/java/org/jclouds/azure/management/domain/role/conf/SSH.java b/labs/azure-management/src/main/java/org/jclouds/azure/management/domain/role/conf/SSH.java
new file mode 100644
index 0000000..4e26587
--- /dev/null
+++ b/labs/azure-management/src/main/java/org/jclouds/azure/management/domain/role/conf/SSH.java
@@ -0,0 +1,50 @@
+package org.jclouds.azure.management.domain.role.conf;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlElementWrapper;
+import javax.xml.bind.annotation.XmlRootElement;
+
+@XmlRootElement(name = "SSH")
+public class SSH {
+
+   /**
+    * Specifies the collection of SSH public keys.
+    */
+   @XmlElementWrapper(name = "PublicKeys")
+   @XmlElement(name = "PublicKey")
+   private List<PublicKey> publicKeys = new ArrayList<PublicKey>(0);
+
+   /**
+    * Specifies the public key.
+    */
+   @XmlElementWrapper(name = "KeyPairs")
+   @XmlElement(name = "KeyPair")
+   private List<KeyPair> keyPairs = new ArrayList<KeyPair>(0);
+
+   public SSH() {
+   }
+
+   public List<PublicKey> getPublicKeys() {
+      return publicKeys;
+   }
+
+   public void setPublicKeys(List<PublicKey> publicKeys) {
+      this.publicKeys = publicKeys;
+   }
+
+   public List<KeyPair> getKeyPairs() {
+      return keyPairs;
+   }
+
+   public void setKeyPairs(List<KeyPair> keyPairs) {
+      this.keyPairs = keyPairs;
+   }
+
+   @Override
+   public String toString() {
+      return "SSH [publicKeys=" + publicKeys + ", keyPairs=" + keyPairs + "]";
+   }
+}
diff --git a/labs/azure-management/src/main/java/org/jclouds/azure/management/domain/role/conf/SSHKey.java b/labs/azure-management/src/main/java/org/jclouds/azure/management/domain/role/conf/SSHKey.java
new file mode 100644
index 0000000..83c617f
--- /dev/null
+++ b/labs/azure-management/src/main/java/org/jclouds/azure/management/domain/role/conf/SSHKey.java
@@ -0,0 +1,39 @@
+package org.jclouds.azure.management.domain.role.conf;
+
+import javax.xml.bind.annotation.XmlElement;
+
+public class SSHKey {
+
+   /**
+    * Specifies the SHA1 fingerprint of an X509 certificate associated with the hosted service that
+    * includes the SSH public key.
+    */
+   @XmlElement(required = true, name = "FingerPrint")
+   protected String fingerPrint;
+
+   /**
+    * Specifies the full path of a file, on the virtual machine, which stores the SSH public key. If
+    * the file already exists, the specified key is appended to the file.
+    */
+   @XmlElement(required = true, name = "Path")
+   protected String path;
+
+   public SSHKey() {
+   }
+
+   public String getFingerPrint() {
+      return fingerPrint;
+   }
+
+   public void setFingerPrint(String fingerPrint) {
+      this.fingerPrint = fingerPrint;
+   }
+
+   public String getPath() {
+      return path;
+   }
+
+   public void setPath(String path) {
+      this.path = path;
+   }
+}
diff --git a/labs/azure-management/src/main/java/org/jclouds/azure/management/domain/role/conf/WindowsProvisioningConfiguration.java b/labs/azure-management/src/main/java/org/jclouds/azure/management/domain/role/conf/WindowsProvisioningConfiguration.java
new file mode 100644
index 0000000..038ebc3
--- /dev/null
+++ b/labs/azure-management/src/main/java/org/jclouds/azure/management/domain/role/conf/WindowsProvisioningConfiguration.java
@@ -0,0 +1,123 @@
+package org.jclouds.azure.management.domain.role.conf;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.TimeZone;
+
+//@XmlRootElement(name = "ConfigurationSet")
+public class WindowsProvisioningConfiguration extends ConfigurationSet {
+
+   public final static String ID = "WindowsProvisioningConfiguration";
+
+   /**
+    * Specifies the computer name for the virtual machine
+    * 
+    * Computer names must be 1 to 15 characters in length.
+    */
+   // @XmlElement(name = "ComputerName")
+   private String computerName;
+   /**
+    * Specifies the base-64 encoded string representing the administrator password to use for the
+    * virtual machine.
+    */
+   // @XmlElement(required = true, name = "AdminPassword")
+   private String adminPassword;
+   /**
+    * Specifies whether the user must change the administrator password on first logon. The default
+    * value is false.
+    */
+   // @XmlElement(required = true, name = "ResetPasswordOnFirstLogon")
+   private Boolean resetPasswordOnFirstLogon;
+   /**
+    * Specifies whether automatic updates are enabled for the virtual machine. The default value is
+    * true.
+    */
+   // @XmlElement(name = "EnableAutomaticUpdates")
+   private Boolean enableAutomaticUpdates;
+   /**
+    * Specifies the time zone for the virtual machine.
+    */
+   // @XmlElement(name = "TimeZone")
+   private TimeZone timeZone;
+   /**
+    * Contains properties that specify a domain to which the virtual machine will be joined. The
+    * DomainJoin node contains either credentials or provisioning information.
+    */
+   // @XmlElement(name = "DomainJoin")
+   private DomainJoin domainJoin;
+   /**
+    * Contains a list of service certificates with which to provision to the new virtual machine.
+    */
+   // @XmlElementWrapper(required = true, name = "StoredCertificateSettings")
+   // @XmlElement(name = "CertificateSetting")
+   private List<CertificateSetting> storedCertificateSettings = new ArrayList<CertificateSetting>();
+
+   public WindowsProvisioningConfiguration() {
+
+   }
+
+   public String getComputerName() {
+      return computerName;
+   }
+
+   public void setComputerName(String computerName) {
+      this.computerName = computerName;
+   }
+
+   public String getAdminPassword() {
+      return adminPassword;
+   }
+
+   public void setAdminPassword(String adminPassword) {
+      this.adminPassword = adminPassword;
+   }
+
+   public Boolean getResetPasswordOnFirstLogon() {
+      return resetPasswordOnFirstLogon;
+   }
+
+   public void setResetPasswordOnFirstLogon(Boolean resetPasswordOnFirstLogon) {
+      this.resetPasswordOnFirstLogon = resetPasswordOnFirstLogon;
+   }
+
+   public Boolean getEnableAutomaticUpdates() {
+      return enableAutomaticUpdates;
+   }
+
+   public void setEnableAutomaticUpdates(Boolean enableAutomaticUpdates) {
+      this.enableAutomaticUpdates = enableAutomaticUpdates;
+   }
+
+   public TimeZone getTimeZone() {
+      return timeZone;
+   }
+
+   public void setTimeZone(TimeZone timeZone) {
+      this.timeZone = timeZone;
+   }
+
+   public DomainJoin getDomainJoin() {
+      return domainJoin;
+   }
+
+   public void setDomainJoin(DomainJoin domainJoin) {
+      this.domainJoin = domainJoin;
+   }
+
+   public List<CertificateSetting> getStoredCertificateSettings() {
+      return storedCertificateSettings;
+   }
+
+   public void setStoredCertificateSettings(List<CertificateSetting> storedCertificateSettings) {
+      this.storedCertificateSettings = storedCertificateSettings;
+   }
+
+   @Override
+   public String toString() {
+      return "WindowsProvisioningConfigurationSet [computerName=" + computerName + ", adminPassword=" + adminPassword
+               + ", resetPasswordOnFirstLogon=" + resetPasswordOnFirstLogon + ", enableAutomaticUpdates="
+               + enableAutomaticUpdates + ", timeZone=" + timeZone + ", domainJoin=" + domainJoin
+               + ", storedCertificateSettings=" + storedCertificateSettings + "]";
+   }
+
+}
diff --git a/labs/azure-management/src/main/java/org/jclouds/azure/management/domain/role/conf/package-info.java b/labs/azure-management/src/main/java/org/jclouds/azure/management/domain/role/conf/package-info.java
new file mode 100644
index 0000000..2c8810b
--- /dev/null
+++ b/labs/azure-management/src/main/java/org/jclouds/azure/management/domain/role/conf/package-info.java
@@ -0,0 +1,27 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+@XmlSchema(namespace = "http://schemas.microsoft.com/windowsazure", elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED)
+@XmlAccessorType(XmlAccessType.FIELD)
+//@XmlJavaTypeAdapters({@XmlJavaTypeAdapter(NetworkConfigurationSetAdapter.class),@XmlJavaTypeAdapter(LinuxProvisioningConfigurationSetAdapter.class)})
+package org.jclouds.azure.management.domain.role.conf;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlSchema;
+
diff --git a/labs/azure-management/src/main/java/org/jclouds/azure/management/domain/role/package-info.java b/labs/azure-management/src/main/java/org/jclouds/azure/management/domain/role/package-info.java
new file mode 100644
index 0000000..b6367ef
--- /dev/null
+++ b/labs/azure-management/src/main/java/org/jclouds/azure/management/domain/role/package-info.java
@@ -0,0 +1,27 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+@XmlSchema(namespace = "http://schemas.microsoft.com/windowsazure", elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED)
+@XmlAccessorType(XmlAccessType.FIELD)
+//@XmlJavaTypeAdapters({@XmlJavaTypeAdapter(NetworkConfigurationSetAdapter.class),@XmlJavaTypeAdapter(LinuxProvisioningConfigurationSetAdapter.class)})
+package org.jclouds.azure.management.domain.role;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlSchema;
+
diff --git a/labs/azure-management/src/main/java/org/jclouds/azure/management/features/DiskApi.java b/labs/azure-management/src/main/java/org/jclouds/azure/management/features/DiskApi.java
new file mode 100644
index 0000000..12e6347
--- /dev/null
+++ b/labs/azure-management/src/main/java/org/jclouds/azure/management/features/DiskApi.java
@@ -0,0 +1,50 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.azure.management.features;
+
+import java.util.Set;
+import java.util.concurrent.TimeUnit;
+
+import org.jclouds.azure.management.domain.Disk;
+import org.jclouds.concurrent.Timeout;
+
+/**
+ * The Service Management API includes operations for managing the disks in your subscription.
+ * 
+ * @see <a href="http://msdn.microsoft.com/en-us/library/jj157188">docs</a>
+ * @see DiskAsyncApi
+ * @author Gerald Pereira
+ */
+@Timeout(duration = 30, timeUnit = TimeUnit.SECONDS)
+public interface DiskApi {
+
+   /**
+    * The List Disks operation retrieves a list of the disks in your image repository.
+    */
+   Set<Disk> list();
+
+   /**
+    * The Delete Disk operation deletes the specified data or operating system disk from your image
+    * repository.
+    * 
+    * @return request id or null, if not found
+    * 
+    */
+   String delete(String diskName);
+}
diff --git a/labs/azure-management/src/main/java/org/jclouds/azure/management/features/DiskAsyncApi.java b/labs/azure-management/src/main/java/org/jclouds/azure/management/features/DiskAsyncApi.java
new file mode 100644
index 0000000..e067bee
--- /dev/null
+++ b/labs/azure-management/src/main/java/org/jclouds/azure/management/features/DiskAsyncApi.java
@@ -0,0 +1,67 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.azure.management.features;
+
+import java.util.Set;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.core.MediaType;
+
+import org.jclouds.azure.management.domain.Disk;
+import org.jclouds.azure.management.functions.ParseRequestIdHeader;
+import org.jclouds.azure.management.xml.ListDisksHandler;
+import org.jclouds.rest.annotations.ExceptionParser;
+import org.jclouds.rest.annotations.Headers;
+import org.jclouds.rest.annotations.ResponseParser;
+import org.jclouds.rest.annotations.SkipEncoding;
+import org.jclouds.rest.annotations.XMLResponseParser;
+import org.jclouds.rest.functions.ReturnEmptySetOnNotFoundOr404;
+import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404;
+
+import com.google.common.util.concurrent.ListenableFuture;
+
+/**
+ * The Service Management API includes operations for managing the virtual machines Disk in your
+ * subscription.
+ * 
+ * @see <a href="http://msdn.microsoft.com/en-us/library/jj157188">docs</a>
+ * @see DiskApi
+ * @author Gerald Pereira
+ */
+@SkipEncoding('/')
+@Headers(keys = "x-ms-version", values = "2012-03-01")
+public interface DiskAsyncApi {
+
+   @GET
+   @Path("/services/disks")
+   @XMLResponseParser(ListDisksHandler.class)
+   @ExceptionParser(ReturnEmptySetOnNotFoundOr404.class)
+   @Consumes(MediaType.APPLICATION_XML)
+   ListenableFuture<Set<Disk>> list();
+
+   @DELETE
+   @Path("/services/disks/{diskName}")
+   @ExceptionParser(ReturnNullOnNotFoundOr404.class)
+   @ResponseParser(ParseRequestIdHeader.class)
+   ListenableFuture<String> delete(@PathParam("diskName") String imageName);
+}
diff --git a/labs/azure-management/src/main/java/org/jclouds/azure/management/features/HostedServiceApi.java b/labs/azure-management/src/main/java/org/jclouds/azure/management/features/HostedServiceApi.java
new file mode 100644
index 0000000..93d5cad
--- /dev/null
+++ b/labs/azure-management/src/main/java/org/jclouds/azure/management/features/HostedServiceApi.java
@@ -0,0 +1,143 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.azure.management.features;
+
+import java.util.Set;
+import java.util.concurrent.TimeUnit;
+
+import org.jclouds.azure.management.domain.Deployment;
+import org.jclouds.azure.management.domain.HostedService;
+import org.jclouds.azure.management.domain.HostedServiceWithDetailedProperties;
+import org.jclouds.azure.management.options.CreateHostedServiceOptions;
+import org.jclouds.concurrent.Timeout;
+
+/**
+ * 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>
+ * @see HostedServiceAsyncApi
+ * @author Gerald Pereira, Adrian Cole
+ */
+@Timeout(duration = 30, timeUnit = TimeUnit.SECONDS)
+public interface HostedServiceApi {
+
+   /**
+    * The List Hosted Services operation lists the hosted services available under the current
+    * subscription.
+    * 
+    * @return the response object
+    */
+   Set<HostedServiceWithDetailedProperties> list();
+
+   /**
+    * The Create Hosted Service operation creates a new hosted service in Windows Azure.
+    * 
+    * @param serviceName
+    *           A name for the hosted service that is unique within Windows Azure. This name is the
+    *           DNS prefix name and can be used to access the hosted service.
+    * 
+    *           For example: http://ServiceName.cloudapp.net//
+    * @param label
+    *           The name can be used identify the storage account for your tracking purposes. The
+    *           name can be up to 100 characters in length.
+    * @param location
+    *           The location where the hosted service will be created.
+    * @return the requestId to track this async request progress
+    * 
+    * @see <a href="http://msdn.microsoft.com/en-us/library/ee460812">docs</a>
+    */
+   String createServiceWithLabelInLocation(String serviceName, String label, String location);
+
+   /**
+    * same as {@link #createServiceWithLabelInLocation(String, String, String)} , except you can
+    * specify optional parameters such as extended properties or a description.
+    * 
+    * @param options
+    *           parameters such as extended properties or a description.
+    */
+   String createServiceWithLabelInLocation(String serviceName, String label, String location,
+            CreateHostedServiceOptions options);
+
+   /**
+    * The Get Hosted Service Properties operation retrieves system properties for the specified
+    * hosted service. These properties include the service name and service type; the name of the
+    * affinity group to which the service belongs, or its location if it is not part of an affinity
+    * group.
+    * 
+    * @param serviceName
+    *           the unique DNS Prefix value in the Windows Azure Management Portal
+    */
+   HostedService get(String serviceName);
+
+   /**
+    * like {@link #get(String)}, except additional data such as status and deployment information is
+    * returned.
+    * 
+    * @param serviceName
+    *           the unique DNS Prefix value in the Windows Azure Management Portal
+    */
+   HostedServiceWithDetailedProperties getDetails(String serviceName);
+
+   /**
+    * The Delete Hosted Service operation deletes the specified hosted service from Windows Azure.
+    * 
+    * @param serviceName
+    *           the unique DNS Prefix value in the Windows Azure Management Portal
+    *           
+    * @return request id or null, if not found
+    */
+   String delete(String serviceName);
+
+   /**
+    * http://msdn.microsoft.com/en-us/library/ee460813
+    * 
+    * @param serviceName
+    *           the unique DNS Prefix value in the Windows Azure Management Portal
+    * @param deploymentSlotName
+    *           "staging" or "production", depending on where you wish to deploy your service
+    *           package
+    * @param createDeployment
+    *           the deployment to create
+    */
+ // This is a PaaS REST service !
+//   void createDeployment(String serviceName, String deploymentSlotName, CreateDeployment createDeployment);
+
+   /**
+    * The Delete Deployment operation deletes the specified deployment from Windows Azure.
+    * 
+    * @param serviceName
+    *           the unique DNS Prefix value in the Windows Azure Management Portal
+    * @param deploylentName
+    *           the unique DNS Prefix value in the Windows Azure Management Portal
+    */
+   String deleteDeployment(String serviceName, String deploymentName);
+   
+   
+   /**
+    * The Get Deployment operation returns the specified deployment from Windows Azure.
+    * 
+    * @param serviceName
+    *           the unique DNS Prefix value in the Windows Azure Management Portal
+    * @param deploylentName
+    *           the unique DNS Prefix value in the Windows Azure Management Portal
+    */
+   Deployment getDeployment(String serviceName, String deploymentName);
+
+}
diff --git a/labs/azure-management/src/main/java/org/jclouds/azure/management/features/HostedServiceAsyncApi.java b/labs/azure-management/src/main/java/org/jclouds/azure/management/features/HostedServiceAsyncApi.java
new file mode 100644
index 0000000..9e1f7b1
--- /dev/null
+++ b/labs/azure-management/src/main/java/org/jclouds/azure/management/features/HostedServiceAsyncApi.java
@@ -0,0 +1,159 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.azure.management.features;
+
+import java.util.Set;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+
+import org.jclouds.azure.management.binders.BindCreateHostedServiceToXmlPayload;
+import org.jclouds.azure.management.domain.Deployment;
+import org.jclouds.azure.management.domain.HostedService;
+import org.jclouds.azure.management.domain.HostedServiceWithDetailedProperties;
+import org.jclouds.azure.management.functions.ParseRequestIdHeader;
+import org.jclouds.azure.management.options.CreateHostedServiceOptions;
+import org.jclouds.azure.management.xml.DeploymentHandler;
+import org.jclouds.azure.management.xml.HostedServiceHandler;
+import org.jclouds.azure.management.xml.HostedServiceWithDetailedPropertiesHandler;
+import org.jclouds.azure.management.xml.ListHostedServicesHandler;
+import org.jclouds.rest.annotations.ExceptionParser;
+import org.jclouds.rest.annotations.Headers;
+import org.jclouds.rest.annotations.MapBinder;
+import org.jclouds.rest.annotations.PayloadParam;
+import org.jclouds.rest.annotations.QueryParams;
+import org.jclouds.rest.annotations.ResponseParser;
+import org.jclouds.rest.annotations.SkipEncoding;
+import org.jclouds.rest.annotations.XMLResponseParser;
+import org.jclouds.rest.functions.ReturnEmptySetOnNotFoundOr404;
+import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404;
+import org.jclouds.rest.functions.ReturnVoidOnNotFoundOr404;
+
+import com.google.common.util.concurrent.ListenableFuture;
+
+/**
+ * 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>
+ * @see HostedServiceApi
+ * @author Gerald Pereira, Adrian Cole
+ */
+@SkipEncoding('/')
+@Headers(keys = "x-ms-version", values = "2012-03-01")
+public interface HostedServiceAsyncApi {
+
+   /**
+    * @see HostedServiceApi#list()
+    */
+   @GET
+   @Path("/services/hostedservices")
+   @XMLResponseParser(ListHostedServicesHandler.class)
+   @ExceptionParser(ReturnEmptySetOnNotFoundOr404.class)
+   @Consumes(MediaType.APPLICATION_XML)
+   ListenableFuture<Set<HostedServiceWithDetailedProperties>> list();
+
+   /**
+    * @see HostedServiceApi#createServiceWithLabelInLocation(String, String, String)
+    */
+   @POST
+   @Path("/services/hostedservices")
+   @MapBinder(BindCreateHostedServiceToXmlPayload.class)
+   @Produces(MediaType.APPLICATION_XML)
+   @ResponseParser(ParseRequestIdHeader.class)
+   ListenableFuture<String> createServiceWithLabelInLocation(@PayloadParam("serviceName") String serviceName,
+            @PayloadParam("label") String label, @PayloadParam("location") String location);
+
+   /**
+    * @see HostedServiceApi#createServiceWithLabelInLocation(String, String, String,
+    *      CreateHostedServiceOptions)
+    */
+   @POST
+   @Path("/services/hostedservices")
+   @MapBinder(BindCreateHostedServiceToXmlPayload.class)
+   @Produces(MediaType.APPLICATION_XML)
+   @ResponseParser(ParseRequestIdHeader.class)
+   ListenableFuture<String> createServiceWithLabelInLocation(@PayloadParam("serviceName") String serviceName,
+            @PayloadParam("label") String label, @PayloadParam("location") String location,
+            @PayloadParam("options") CreateHostedServiceOptions options);
+
+   /**
+    * @see HostedServiceApi#get(String)
+    */
+   @GET
+   @Path("/services/hostedservices/{serviceName}")
+   @XMLResponseParser(HostedServiceHandler.class)
+   @ExceptionParser(ReturnNullOnNotFoundOr404.class)
+   @Consumes(MediaType.APPLICATION_XML)
+   ListenableFuture<HostedService> get(@PathParam("serviceName") String serviceName);
+
+   /**
+    * @see HostedServiceApi#getDetails(String)
+    */
+   @GET
+   @Path("/services/hostedservices/{serviceName}")
+   @QueryParams(keys = "embed-detail", values = "true")
+   @XMLResponseParser(HostedServiceWithDetailedPropertiesHandler.class)
+   @ExceptionParser(ReturnNullOnNotFoundOr404.class)
+   @Consumes(MediaType.APPLICATION_XML)
+   ListenableFuture<HostedServiceWithDetailedProperties> getDetails(@PathParam("serviceName") String serviceName);
+
+   /**
+    * @see HostedServiceApi#delete(String)
+    */
+   @DELETE
+   @Path("/services/hostedservices/{serviceName}")
+   @ExceptionParser(ReturnNullOnNotFoundOr404.class)
+   @ResponseParser(ParseRequestIdHeader.class)
+   ListenableFuture<String> delete(@PathParam("serviceName") String serviceName);
+
+ // This is a PaaS REST service !
+//   @POST
+//   @Path("/services/hostedservices/{serviceName}/deploymentslots/{deploymentSlotName}")
+//   @Produces(MediaType.APPLICATION_ATOM_XML)
+//   @Consumes(MediaType.TEXT_PLAIN)
+//   @ExceptionParser(ReturnNullOnNotFoundOr404.class)
+//   ListenableFuture<Void> createDeployment(@PathParam("serviceName") String serviceName,
+//            @PathParam("deploymentSlotName") String deploymentSlotName,
+//            @BinderParam(BindToXMLPayload.class) CreateDeployment createDeployment);
+
+   @DELETE
+   @Path("/services/hostedservices/{serviceName}/deployments/{deploymentName}")
+   @ExceptionParser(ReturnVoidOnNotFoundOr404.class)
+   @ResponseParser(ParseRequestIdHeader.class)
+   ListenableFuture<String> deleteDeployment(@PathParam("serviceName") String serviceName,
+            @PathParam("deploymentName") String deploymentName);
+   
+   
+   /**
+    * @see HostedServiceApi#get(String,String)
+    */
+   @GET
+   @Path("/services/hostedservices/{serviceName}/deployments/{deploymentName}")
+   @XMLResponseParser(DeploymentHandler.class)
+   @ExceptionParser(ReturnVoidOnNotFoundOr404.class)
+   @Consumes(MediaType.APPLICATION_XML)
+   ListenableFuture<Deployment> getDeployment(@PathParam("serviceName") String serviceName, @PathParam("deploymentName") String deploymentName);
+}
diff --git a/labs/azure-management/src/main/java/org/jclouds/azure/management/features/LocationApi.java b/labs/azure-management/src/main/java/org/jclouds/azure/management/features/LocationApi.java
new file mode 100644
index 0000000..25a4aca
--- /dev/null
+++ b/labs/azure-management/src/main/java/org/jclouds/azure/management/features/LocationApi.java
@@ -0,0 +1,47 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.azure.management.features;
+
+import java.util.Set;
+import java.util.concurrent.TimeUnit;
+
+import org.jclouds.azure.management.domain.Location;
+import org.jclouds.concurrent.Timeout;
+
+/**
+ * The Service Management API includes operations for listing the available data center locations
+ * for a hosted service in your subscription.
+ * <p/>
+ * 
+ * @see <a href="http://msdn.microsoft.com/en-us/library/gg441299" />
+ * @see LocationAsyncApi
+ * @author Adrian Cole
+ */
+@Timeout(duration = 30, timeUnit = TimeUnit.SECONDS)
+public interface LocationApi {
+
+   /**
+    * The List Locations operation lists all of the data center locations that are valid for your
+    * subscription.
+    * 
+    * @return the response object
+    */
+   Set<Location> list();
+
+}
diff --git a/labs/azure-management/src/main/java/org/jclouds/azure/management/features/LocationAsyncApi.java b/labs/azure-management/src/main/java/org/jclouds/azure/management/features/LocationAsyncApi.java
new file mode 100644
index 0000000..8dd1eca
--- /dev/null
+++ b/labs/azure-management/src/main/java/org/jclouds/azure/management/features/LocationAsyncApi.java
@@ -0,0 +1,61 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.azure.management.features;
+
+import java.util.Set;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.core.MediaType;
+
+import org.jclouds.azure.management.domain.Location;
+import org.jclouds.azure.management.xml.ListLocationsHandler;
+import org.jclouds.rest.annotations.ExceptionParser;
+import org.jclouds.rest.annotations.Headers;
+import org.jclouds.rest.annotations.SkipEncoding;
+import org.jclouds.rest.annotations.XMLResponseParser;
+import org.jclouds.rest.functions.ReturnEmptySetOnNotFoundOr404;
+
+import com.google.common.util.concurrent.ListenableFuture;
+
+/**
+ * The Service Management API includes operations for listing the available data center locations
+ * for a hosted service in your subscription.
+ * <p/>
+ * 
+ * @see <a href="http://msdn.microsoft.com/en-us/library/gg441299" />
+ * @see LocationApi
+ * @author Adrian Cole
+ */
+@SkipEncoding('/')
+@Headers(keys = "x-ms-version", values = "2012-03-01")
+public interface LocationAsyncApi {
+
+   /**
+    * @see LocationApi#list()
+    */
+   @GET
+   @Path("/locations")
+   @XMLResponseParser(ListLocationsHandler.class)
+   @ExceptionParser(ReturnEmptySetOnNotFoundOr404.class)
+   @Consumes(MediaType.APPLICATION_XML)
+   ListenableFuture<Set<Location>> list();
+
+}
diff --git a/labs/azure-management/src/main/java/org/jclouds/azure/management/features/OSImageApi.java b/labs/azure-management/src/main/java/org/jclouds/azure/management/features/OSImageApi.java
new file mode 100644
index 0000000..ebaceb0
--- /dev/null
+++ b/labs/azure-management/src/main/java/org/jclouds/azure/management/features/OSImageApi.java
@@ -0,0 +1,70 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.azure.management.features;
+
+import java.util.Set;
+import java.util.concurrent.TimeUnit;
+
+import org.jclouds.azure.management.domain.OSImage;
+import org.jclouds.azure.management.domain.OSImageParams;
+import org.jclouds.concurrent.Timeout;
+
+/**
+ * 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>
+ * @see OSImageAsyncApi
+ * @author Gerald Pereira, Adrian Cole
+ */
+@Timeout(duration = 30, timeUnit = TimeUnit.SECONDS)
+public interface OSImageApi {
+
+   /**
+    * The List Hosted Services operation lists the hosted services available under the current
+    * subscription.
+    * 
+    * @return the response object
+    */
+   Set<OSImage> list();
+
+   /**
+    * The Add OS Image operation adds an OS image that is currently stored in a storage account in your subscription to the image repository.
+    * 
+    * @param params
+    *           the required parameters needed to add an image
+    */
+   void add(OSImageParams params);
+   
+   /**
+    * The Update OS Image operation updates an OS image that in your image repository.
+    * 
+    * @param params
+    *           the required parameters needed to update an image
+    */
+   void update(OSImageParams params);
+   
+   /**
+    * The Delete Hosted Service operation deletes the specified hosted service from Windows Azure.
+    * 
+    * @param imageName
+    *           the unique DNS Prefix value in the Windows Azure Management Portal
+    */
+   void delete(String imageName);
+
+}
diff --git a/labs/azure-management/src/main/java/org/jclouds/azure/management/features/OSImageAsyncApi.java b/labs/azure-management/src/main/java/org/jclouds/azure/management/features/OSImageAsyncApi.java
new file mode 100644
index 0000000..88c1793
--- /dev/null
+++ b/labs/azure-management/src/main/java/org/jclouds/azure/management/features/OSImageAsyncApi.java
@@ -0,0 +1,95 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.azure.management.features;
+
+import java.util.Set;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+
+import org.jclouds.azure.management.binders.BindOSImageParamsToXmlPayload;
+import org.jclouds.azure.management.domain.OSImage;
+import org.jclouds.azure.management.domain.OSImageParams;
+import org.jclouds.azure.management.functions.OSImageParamsName;
+import org.jclouds.azure.management.xml.ListOSImagesHandler;
+import org.jclouds.rest.annotations.BinderParam;
+import org.jclouds.rest.annotations.ExceptionParser;
+import org.jclouds.rest.annotations.Headers;
+import org.jclouds.rest.annotations.ParamParser;
+import org.jclouds.rest.annotations.SkipEncoding;
+import org.jclouds.rest.annotations.XMLResponseParser;
+import org.jclouds.rest.functions.ReturnEmptySetOnNotFoundOr404;
+import org.jclouds.rest.functions.ReturnVoidOnNotFoundOr404;
+
+import com.google.common.util.concurrent.ListenableFuture;
+
+/**
+ * The Service Management API includes operations for managing the OS images in your subscription.
+ * 
+ * @see <a href="http://msdn.microsoft.com/en-us/library/jj5775">docs</a>
+ * @see OSImageApi
+ * @author Gerald Pereira, Adrian Cole
+ */
+@SkipEncoding('/')
+@Headers(keys = "x-ms-version", values = "2012-03-01")
+public interface OSImageAsyncApi {
+
+   /**
+    * @see OSImageApi#list()
+    */
+   @GET
+   @Path("/services/images")
+   @XMLResponseParser(ListOSImagesHandler.class)
+   @ExceptionParser(ReturnEmptySetOnNotFoundOr404.class)
+   @Consumes(MediaType.APPLICATION_XML)
+   ListenableFuture<Set<OSImage>> list();
+
+   /**
+    * @see OSImageApi#add(String)
+    */
+   @POST
+   @Path("/services/images")
+   @Produces(MediaType.APPLICATION_XML)
+   ListenableFuture<Void> add(@BinderParam(BindOSImageParamsToXmlPayload.class) OSImageParams params);
+
+   /**
+    * @see OSImageApi#update(String)
+    */
+   @PUT
+   @Path("/services/images/{imageName}")
+   @Produces(MediaType.APPLICATION_XML)
+   ListenableFuture<Void> update(
+            @PathParam("imageName") @ParamParser(OSImageParamsName.class) @BinderParam(BindOSImageParamsToXmlPayload.class) OSImageParams params);
+
+   /**
+    * @see OSImageApi#delete(String)
+    */
+   @DELETE
+   @Path("/services/images/{imageName}")
+   @ExceptionParser(ReturnVoidOnNotFoundOr404.class)
+   ListenableFuture<Void> delete(@PathParam("imageName") String imageName);
+
+}
diff --git a/labs/azure-management/src/main/java/org/jclouds/azure/management/features/OperationApi.java b/labs/azure-management/src/main/java/org/jclouds/azure/management/features/OperationApi.java
new file mode 100644
index 0000000..ec70bc9
--- /dev/null
+++ b/labs/azure-management/src/main/java/org/jclouds/azure/management/features/OperationApi.java
@@ -0,0 +1,38 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.azure.management.features;
+
+import java.util.concurrent.TimeUnit;
+
+import org.jclouds.azure.management.domain.Operation;
+import org.jclouds.concurrent.Timeout;
+
+/**
+ * The Service Management API includes one operation for tracking the progress of asynchronous requests.
+ * 
+ * @see <a href="http://msdn.microsoft.com/en-us/library/ee460796">docs</a>
+ * @see OperationAsyncApi
+ * @author Gerald Pereira
+ */
+@Timeout(duration = 30, timeUnit = TimeUnit.SECONDS)
+public interface OperationApi {
+
+   Operation get(String requestId);
+
+}
diff --git a/labs/azure-management/src/main/java/org/jclouds/azure/management/features/OperationAsyncApi.java b/labs/azure-management/src/main/java/org/jclouds/azure/management/features/OperationAsyncApi.java
new file mode 100644
index 0000000..892cda9
--- /dev/null
+++ b/labs/azure-management/src/main/java/org/jclouds/azure/management/features/OperationAsyncApi.java
@@ -0,0 +1,55 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.azure.management.features;
+
+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.azure.management.domain.Operation;
+import org.jclouds.azure.management.xml.OperationHandler;
+import org.jclouds.rest.annotations.ExceptionParser;
+import org.jclouds.rest.annotations.Headers;
+import org.jclouds.rest.annotations.SkipEncoding;
+import org.jclouds.rest.annotations.XMLResponseParser;
+import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404;
+
+import com.google.common.util.concurrent.ListenableFuture;
+
+/**
+ * The Service Management API includes one operation for tracking the progress of asynchronous requests.
+ * 
+ * @see <a href="http://msdn.microsoft.com/en-us/library/ee460796">docs</a>
+ * @see OperationApi
+ * @author Gerald Pereira
+ */
+@SkipEncoding('/')
+@Headers(keys = "x-ms-version", values = "2012-03-01")
+public interface OperationAsyncApi {
+
+   @GET
+   @Path("/operations/{request-id}")
+   @XMLResponseParser(OperationHandler.class)
+   @ExceptionParser(ReturnNullOnNotFoundOr404.class)
+   @Consumes(MediaType.APPLICATION_XML)
+   ListenableFuture<Operation> get(@PathParam("request-id") String requestId);
+
+}
diff --git a/labs/azure-management/src/main/java/org/jclouds/azure/management/features/RoleApi.java b/labs/azure-management/src/main/java/org/jclouds/azure/management/features/RoleApi.java
new file mode 100644
index 0000000..cb2e97d
--- /dev/null
+++ b/labs/azure-management/src/main/java/org/jclouds/azure/management/features/RoleApi.java
@@ -0,0 +1,95 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.azure.management.features;
+
+import java.util.concurrent.TimeUnit;
+
+import org.jclouds.azure.management.domain.DeploymentParams;
+import org.jclouds.azure.management.domain.role.PersistentVMRole;
+import org.jclouds.concurrent.Timeout;
+
+/**
+ * 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>
+ * @see RoleAsyncApi
+ * @author Gerald Pereira, Adrian Cole
+ */
+@Timeout(duration = 30, timeUnit = TimeUnit.SECONDS)
+public interface RoleApi {
+
+	// FUUUUUU this is not the good REST call !!! Use getDeployment instead :@
+	 PersistentVMRole getRole(String serviceName, String deploymentName,
+	 String roleName);
+
+	// This is a PaaS REST service !
+	// void addRole(String serviceName, String deploymentName, PersistentVMRole
+	// role);
+
+	// This is a PaaS REST service ! => Delete the deployment instead
+	// void deleteRole(String serviceName, String deploymentName, String
+	// roleName);
+
+	String restartRole(String serviceName, String deploymentName,
+			String roleName);
+
+//	@Deprecated
+//	String createVirtualMachineDeployment(String serviceName,
+//			Deployment deployment);
+
+	/**
+	 * http://msdn.microsoft.com/en-us/library/jj157194
+	 * 
+	 * @param serviceName
+	 * @param deploymentParams
+	 * @return
+	 */
+	String createDeployment(String serviceName,
+			DeploymentParams deploymentParams);
+
+	/**
+	 * http://msdn.microsoft.com/en-us/library/jj157201
+	 * 
+	 * @return
+	 */
+	String captureRole(String serviceName, String deploymentName,
+			String roleName, String imageName, String imageLabel);
+	
+	/**
+	 * http://msdn.microsoft.com/en-us/library/jj157195
+	 * @param serviceName
+	 * @param deploymentName
+	 * @param roleName
+	 * @return
+	 */
+	String shutdownRole(String serviceName, String deploymentName,
+			String roleName);
+	
+	/**
+	 * http://msdn.microsoft.com/en-us/library/jj157189
+	 * @param serviceName
+	 * @param deploymentName
+	 * @param roleName
+	 * @return
+	 */
+	String startRole(String serviceName, String deploymentName,
+			String roleName);
+
+}
diff --git a/labs/azure-management/src/main/java/org/jclouds/azure/management/features/RoleAsyncApi.java b/labs/azure-management/src/main/java/org/jclouds/azure/management/features/RoleAsyncApi.java
new file mode 100644
index 0000000..9e9833b
--- /dev/null
+++ b/labs/azure-management/src/main/java/org/jclouds/azure/management/features/RoleAsyncApi.java
@@ -0,0 +1,162 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.azure.management.features;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+
+import org.jclouds.azure.management.binders.BindDeploymentParamsToXmlPayload;
+import org.jclouds.azure.management.domain.DeploymentParams;
+import org.jclouds.azure.management.domain.role.PersistentVMRole;
+import org.jclouds.azure.management.functions.ParseRequestIdHeader;
+import org.jclouds.rest.annotations.BinderParam;
+import org.jclouds.rest.annotations.ExceptionParser;
+import org.jclouds.rest.annotations.Headers;
+import org.jclouds.rest.annotations.JAXBResponseParser;
+import org.jclouds.rest.annotations.Payload;
+import org.jclouds.rest.annotations.PayloadParam;
+import org.jclouds.rest.annotations.ResponseParser;
+import org.jclouds.rest.annotations.SkipEncoding;
+import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404;
+
+import com.google.common.util.concurrent.ListenableFuture;
+
+/**
+ * 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>
+ * @see RoleApi
+ * @author Gerald Pereira, Adrian Cole
+ */
+@SkipEncoding('/')
+@Headers(keys = "x-ms-version", values = "2012-03-01")
+public interface RoleAsyncApi {
+
+	 @GET
+	 @Path("/services/hostedservices/{serviceName}/deployments/{deploymentName}/roles/{roleName}")
+	 @Consumes(MediaType.APPLICATION_ATOM_XML)
+	 @JAXBResponseParser
+	 @ExceptionParser(ReturnNullOnNotFoundOr404.class)
+	 ListenableFuture<PersistentVMRole> getRole(@PathParam("serviceName")
+	 String serviceName,
+	 @PathParam("deploymentName") String deploymentName,
+	 @PathParam("roleName") String roleName);
+
+	// This is a PaaS REST service ! => Delete the deployment instead
+	// @DELETE
+	// @Path("/services/hostedservices/{serviceName}/deployments/{deploymentName}/roles/{roleName}")
+	// @Consumes(MediaType.APPLICATION_ATOM_XML)
+	// @JAXBResponseParser
+	// @ExceptionParser(ReturnNullOnNotFoundOr404.class)
+	// ListenableFuture<Void> deleteRole(@PathParam("serviceName") String
+	// serviceName,
+	// @PathParam("deploymentName") String deploymentName,
+	// @PathParam("roleName") String roleName);
+
+	@POST
+	// Warning : the url in the documentation is WRONG ! @see
+	// http://social.msdn.microsoft.com/Forums/pl-PL/WAVirtualMachinesforWindows/thread/7ba2367b-e450-49e0-89e4-46c240e9d213
+	@Path("/services/hostedservices/{serviceName}/deployments/{deploymentName}/roleInstances/{roleName}/Operations")
+	@Consumes(MediaType.APPLICATION_ATOM_XML)
+	@Produces(MediaType.APPLICATION_ATOM_XML)
+	@ExceptionParser(ReturnNullOnNotFoundOr404.class)
+	@ResponseParser(ParseRequestIdHeader.class)
+	@Payload(value = "<RestartRoleOperation xmlns=\"http://schemas.microsoft.com/windowsazure\" xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\"><OperationType>RestartRoleOperation</OperationType></RestartRoleOperation>")
+	ListenableFuture<String> restartRole(
+			@PathParam("serviceName") String serviceName,
+			@PathParam("deploymentName") String deploymentName,
+			@PathParam("roleName") String roleName);
+
+	// This is a PaaS REST service !
+	// @POST
+	// @Path("/services/hostedservices/{serviceName}/deployments/{deploymentName}/roles")
+	// @Produces(MediaType.APPLICATION_ATOM_XML)
+	// @Consumes(MediaType.TEXT_PLAIN)
+	// @ExceptionParser(ReturnNullOnNotFoundOr404.class)
+	// ListenableFuture<Void> addRole(@PathParam("serviceName") String
+	// serviceName,
+	// @PathParam("deploymentName") String deploymentName,
+	// @BinderParam(BindToXMLPayload.class) PersistentVMRole role);
+
+//	@Deprecated
+//	@POST
+//	@Path("/services/hostedservices/{serviceName}/deployments")
+//	@Produces(MediaType.APPLICATION_ATOM_XML)
+//	@Consumes(MediaType.TEXT_PLAIN)
+//	@ExceptionParser(ReturnNullOnNotFoundOr404.class)
+//	@ResponseParser(ParseRequestIdHeader.class)
+//	ListenableFuture<String> createVirtualMachineDeployment(
+//			@PathParam("serviceName") String serviceName,
+//			@BinderParam(BindToXMLPayload.class) Deployment deployment);
+
+	@POST
+	@Path("/services/hostedservices/{serviceName}/deployments")
+	@Produces(MediaType.APPLICATION_ATOM_XML)
+	@Consumes(MediaType.APPLICATION_ATOM_XML)
+	@ExceptionParser(ReturnNullOnNotFoundOr404.class)
+	@ResponseParser(ParseRequestIdHeader.class)
+	ListenableFuture<String> createDeployment(
+			@PathParam("serviceName") String serviceName,
+			@BinderParam(BindDeploymentParamsToXmlPayload.class) DeploymentParams deploymentParams);
+
+	@POST
+	@Path("/services/hostedservices/{serviceName}/deployments/{deploymentName}/roleInstances/{roleName}/Operations")
+	@Consumes(MediaType.APPLICATION_ATOM_XML)
+	@Produces(MediaType.APPLICATION_ATOM_XML)
+	@ExceptionParser(ReturnNullOnNotFoundOr404.class)
+	@ResponseParser(ParseRequestIdHeader.class)
+	@Payload(value = "<CaptureRoleOperation xmlns=\"http://schemas.microsoft.com/windowsazure\" xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\"><OperationType>CaptureRoleOperation</OperationType><PostCaptureAction>Delete</PostCaptureAction><TargetImageLabel>{imageLabel}</TargetImageLabel><TargetImageName>{imageName}</TargetImageName></CaptureRoleOperation>")
+	ListenableFuture<String> captureRole(
+			@PathParam("serviceName") String serviceName,
+			@PathParam("deploymentName") String deploymentName,
+			@PathParam("roleName") String roleName,
+			@PayloadParam("imageName") String imageName,
+			@PayloadParam("imageLabel") String imageLabel);
+	
+	@POST
+	@Path("/services/hostedservices/{serviceName}/deployments/{deploymentName}/roleInstances/{roleName}/Operations")
+	@Consumes(MediaType.APPLICATION_ATOM_XML)
+	@Produces(MediaType.APPLICATION_ATOM_XML)
+	@ExceptionParser(ReturnNullOnNotFoundOr404.class)
+	@ResponseParser(ParseRequestIdHeader.class)
+	@Payload(value = "<ShutdownRoleOperation xmlns=\"http://schemas.microsoft.com/windowsazure\" xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\"><OperationType>ShutdownRoleOperation</OperationType></ShutdownRoleOperation>")
+	ListenableFuture<String> shutdownRole(
+			@PathParam("serviceName") String serviceName,
+			@PathParam("deploymentName") String deploymentName,
+			@PathParam("roleName") String roleName);
+	
+	@POST
+	@Path("/services/hostedservices/{serviceName}/deployments/{deploymentName}/roleInstances/{roleName}/Operations")
+	@Consumes(MediaType.APPLICATION_ATOM_XML)
+	@Produces(MediaType.APPLICATION_ATOM_XML)
+	@ExceptionParser(ReturnNullOnNotFoundOr404.class)
+	@ResponseParser(ParseRequestIdHeader.class)
+	@Payload(value = "<StartRoleOperation xmlns=\"http://schemas.microsoft.com/windowsazure\" xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\"><OperationType>StartRoleOperation</OperationType></StartRoleOperation>")
+	ListenableFuture<String> startRole(
+			@PathParam("serviceName") String serviceName,
+			@PathParam("deploymentName") String deploymentName,
+			@PathParam("roleName") String roleName);
+
+}
diff --git a/labs/azure-management/src/main/java/org/jclouds/azure/management/functions/OSImageParamsName.java b/labs/azure-management/src/main/java/org/jclouds/azure/management/functions/OSImageParamsName.java
new file mode 100644
index 0000000..e0d018e
--- /dev/null
+++ b/labs/azure-management/src/main/java/org/jclouds/azure/management/functions/OSImageParamsName.java
@@ -0,0 +1,43 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.azure.management.functions;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import javax.inject.Singleton;
+
+import org.jclouds.azure.management.domain.OSImageParams;
+
+import com.google.common.base.Function;
+
+/**
+ * 
+ * @author Adrian Cole
+ */
+@Singleton
+public class OSImageParamsName implements Function<Object, String> {
+   @Override
+   public String apply(Object input) {
+      checkArgument(checkNotNull(input, "input") instanceof OSImageParams,
+               "this function is only valid for OSImageParams!");
+      return checkNotNull(OSImageParams.class.cast(input), "OSImageParams").getName();
+   }
+
+}
diff --git a/labs/azure-management/src/main/java/org/jclouds/azure/management/functions/ParseRequestIdHeader.java b/labs/azure-management/src/main/java/org/jclouds/azure/management/functions/ParseRequestIdHeader.java
new file mode 100644
index 0000000..ea7fcd2
--- /dev/null
+++ b/labs/azure-management/src/main/java/org/jclouds/azure/management/functions/ParseRequestIdHeader.java
@@ -0,0 +1,50 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.azure.management.functions;
+
+import static org.jclouds.http.HttpUtils.releasePayload;
+
+import javax.inject.Singleton;
+
+import org.jclouds.http.HttpResponse;
+
+import com.google.common.base.Function;
+
+/**
+ * Parses an x-ms-request-id the header
+ * 
+ * A value that uniquely identifies a request made against the management service. For an
+ * asynchronous operation, you can call get operation status with the value of the header to
+ * determine whether the operation is complete, has failed, or is still in progress.
+ * 
+ * @author Gerald Pereira
+ */
+@Singleton
+public class ParseRequestIdHeader implements Function<HttpResponse, String> {
+
+   public String apply(HttpResponse from) {
+      releasePayload(from);
+      String requestId = from.getFirstHeaderOrNull("x-ms-request-id");
+      if (requestId != null) {
+         return requestId;
+      }
+      throw new IllegalStateException("did not receive RequestId in: " + from);
+   }
+
+}
\ No newline at end of file
diff --git a/labs/azure-management/src/main/java/org/jclouds/azure/management/options/CreateHostedServiceOptions.java b/labs/azure-management/src/main/java/org/jclouds/azure/management/options/CreateHostedServiceOptions.java
new file mode 100644
index 0000000..75e9c61
--- /dev/null
+++ b/labs/azure-management/src/main/java/org/jclouds/azure/management/options/CreateHostedServiceOptions.java
@@ -0,0 +1,129 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.azure.management.options;
+
+import java.util.Map;
+
+import com.google.common.base.Objects;
+import com.google.common.base.Optional;
+
+/**
+ * Optional parameters for creating a hosted service
+ * 
+ * @see <a href="http://msdn.microsoft.com/en-us/library/gg441304" >docs</a>
+ * 
+ * @author Adrian Cole
+ */
+public class CreateHostedServiceOptions implements Cloneable {
+
+   private Optional<String> description = Optional.absent();
+   private Optional<Map<String, String>> extendedProperties = Optional.absent();
+
+   /**
+    * @see CreateHostedServiceOptions#getDescription()
+    */
+   public CreateHostedServiceOptions description(String description) {
+      this.description = Optional.fromNullable(description);
+      return this;
+   }
+
+   /**
+    * @see CreateHostedServiceOptions#getExtendedProperties()
+    */
+   public CreateHostedServiceOptions extendedProperties(Map<String, String> extendedProperties) {
+      this.extendedProperties = Optional.fromNullable(extendedProperties);
+      return this;
+   }
+
+   /**
+    * A description for the hosted service. The description can be up to 1024 characters in length.
+    */
+   public Optional<String> getDescription() {
+      return description;
+   }
+
+   /**
+    * 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 Optional<Map<String, String>> getExtendedProperties() {
+      return extendedProperties;
+   }
+
+   public static class Builder {
+
+      /**
+       * @see CreateHostedServiceOptions#getDescription()
+       */
+      public static CreateHostedServiceOptions description(String description) {
+         return new CreateHostedServiceOptions().description(description);
+      }
+
+      /**
+       * @see CreateHostedServiceOptions#getExtendedProperties()
+       */
+      public static CreateHostedServiceOptions extendedProperties(Map<String, String> extendedProperties) {
+         return new CreateHostedServiceOptions().extendedProperties(extendedProperties);
+      }
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public int hashCode() {
+      return Objects.hashCode(description, extendedProperties);
+   }
+
+   @Override
+   public CreateHostedServiceOptions clone() {
+      return new CreateHostedServiceOptions().description(description.orNull()).extendedProperties(
+               extendedProperties.orNull());
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public boolean equals(Object obj) {
+      if (this == obj)
+         return true;
+      if (obj == null)
+         return false;
+      if (getClass() != obj.getClass())
+         return false;
+      CreateHostedServiceOptions other = CreateHostedServiceOptions.class.cast(obj);
+      return Objects.equal(this.description, other.description)
+               && Objects.equal(this.extendedProperties, other.extendedProperties);
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public String toString() {
+      return Objects.toStringHelper("").omitNullValues().add("description", description.orNull())
+               .add("extendedProperties", extendedProperties.orNull()).toString();
+   }
+}
diff --git a/labs/azure-management/src/main/java/org/jclouds/azure/management/suppliers/SSLContextWithKeysSupplier.java b/labs/azure-management/src/main/java/org/jclouds/azure/management/suppliers/SSLContextWithKeysSupplier.java
new file mode 100644
index 0000000..1650157
--- /dev/null
+++ b/labs/azure-management/src/main/java/org/jclouds/azure/management/suppliers/SSLContextWithKeysSupplier.java
@@ -0,0 +1,72 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.azure.management.suppliers;
+
+import java.security.KeyManagementException;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.SecureRandom;
+import java.security.UnrecoverableKeyException;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+import javax.net.ssl.KeyManagerFactory;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.TrustManager;
+
+import org.jclouds.http.HttpUtils;
+import org.jclouds.http.config.SSLModule.TrustAllCerts;
+import org.jclouds.rest.annotations.Credential;
+
+import com.google.common.base.Supplier;
+
+/**
+ * 
+ * TODO copied from FGCP, should be put in a common place
+ * 
+ * SSLContext supplier with a configured key manager to enable client authentication with
+ * certificates.
+ * 
+ * @author Dies Koper
+ */
+@Singleton
+public class SSLContextWithKeysSupplier implements Supplier<SSLContext> {
+   private SSLContext sc;
+
+   @Inject
+   SSLContextWithKeysSupplier(KeyStore keyStore, @Credential String keyStorePassword, HttpUtils utils,
+            TrustAllCerts trustAllCerts) throws NoSuchAlgorithmException, KeyStoreException, UnrecoverableKeyException,
+            KeyManagementException {
+
+      TrustManager[] trustManager = null;
+      if (utils.trustAllCerts()) {
+         trustManager = new TrustManager[] { trustAllCerts };
+      }
+      KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
+      kmf.init(keyStore, keyStorePassword.toCharArray());
+      sc = SSLContext.getInstance("TLS");
+      sc.init(kmf.getKeyManagers(), trustManager, new SecureRandom());
+   }
+
+   @Override
+   public SSLContext get() {
+      return sc;
+   }
+}
diff --git a/labs/azure-management/src/main/java/org/jclouds/azure/management/xml/AttachmentHandler.java b/labs/azure-management/src/main/java/org/jclouds/azure/management/xml/AttachmentHandler.java
new file mode 100644
index 0000000..4b5494f
--- /dev/null
+++ b/labs/azure-management/src/main/java/org/jclouds/azure/management/xml/AttachmentHandler.java
@@ -0,0 +1,71 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.azure.management.xml;
+
+import org.jclouds.azure.management.domain.Disk.Attachment;
+import org.jclouds.http.functions.ParseSax;
+import org.jclouds.util.SaxUtils;
+import org.xml.sax.SAXException;
+
+/**
+ * @see <a href="http://msdn.microsoft.com/en-us/library/jj157176" >api</a>
+ * 
+ * @author Adrian Cole
+ */
+public class AttachmentHandler extends ParseSax.HandlerForGeneratedRequestWithResult<Attachment> {
+
+   private StringBuilder currentText = new StringBuilder();
+   private Attachment.Builder builder = Attachment.builder();
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public Attachment getResult() {
+      try {
+         return builder.build();
+      } finally {
+         builder = Attachment.builder();
+      }
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public void endElement(String uri, String name, String qName) throws SAXException {
+      if (qName.equals("HostedServiceName")) {
+         builder.hostedService(SaxUtils.currentOrNull(currentText));
+      } else if (qName.equals("DeploymentName")) {
+         builder.deployment(SaxUtils.currentOrNull(currentText));
+      } else if (qName.equals("RoleName")) {
+         builder.role(SaxUtils.currentOrNull(currentText));
+      }
+      currentText = new StringBuilder();
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public void characters(char ch[], int start, int length) {
+      currentText.append(ch, start, length);
+   }
+
+}
diff --git a/labs/azure-management/src/main/java/org/jclouds/azure/management/xml/DeploymentHandler.java b/labs/azure-management/src/main/java/org/jclouds/azure/management/xml/DeploymentHandler.java
new file mode 100644
index 0000000..aaa3db5
--- /dev/null
+++ b/labs/azure-management/src/main/java/org/jclouds/azure/management/xml/DeploymentHandler.java
@@ -0,0 +1,127 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.azure.management.xml;
+
+import static org.jclouds.util.SaxUtils.currentOrNull;
+import static org.jclouds.util.SaxUtils.equalsOrSuffix;
+
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.jclouds.azure.management.domain.Deployment;
+import org.jclouds.azure.management.domain.DeploymentSlot;
+import org.jclouds.azure.management.domain.DeploymentStatus;
+import org.jclouds.azure.management.domain.InstanceStatus;
+import org.jclouds.azure.management.domain.RoleSize;
+import org.jclouds.crypto.CryptoStreams;
+import org.jclouds.http.functions.ParseSax;
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXException;
+
+/**
+ * @see <a href="http://msdn.microsoft.com/en-us/library/ee460804" >api</a>
+ * @author Gérald Pereira
+ */
+public class DeploymentHandler extends
+		ParseSax.HandlerForGeneratedRequestWithResult<Deployment> {
+
+	private List<String> elements = new ArrayList<String>();
+	protected StringBuilder currentText = new StringBuilder();
+	private Deployment.Builder builder = Deployment.builder();
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public Deployment getResult() {
+		try {
+			return builder.build();
+		} finally {
+			builder = Deployment.builder();
+		}
+	}
+	
+	
+	@Override
+	public void startElement(String uri, String localName, String qName,
+			Attributes attributes) throws SAXException {
+		elements.add(qName);
+	}
+	
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public void endElement(String uri, String name, String qName)
+			throws SAXException {
+		if (equalsOrSuffix(qName, "Name") && "Deployment".equals(elements.get(elements.size()-2))) {
+			builder.deploymentName(currentOrNull(currentText));
+		} else if (equalsOrSuffix(qName, "DeploymentSlot")) {
+			final String dpltSlot = currentOrNull(currentText);
+			if (dpltSlot != null)
+				builder.deploymentSlot(DeploymentSlot.fromValue(dpltSlot));
+		} else if (equalsOrSuffix(qName, "Status")) {
+			String deploymentStatus = currentOrNull(currentText);
+			if (deploymentStatus != null)
+				builder.deploymentStatus(DeploymentStatus
+						.fromValue(deploymentStatus));
+		} else if (equalsOrSuffix(qName, "Label")) {
+			String label = currentOrNull(currentText);
+			if (label != null)
+				builder.deploymentLabel(new String(CryptoStreams.base64(label)));
+		} else if (equalsOrSuffix(qName, "Url")) {
+			final String url = currentOrNull(currentText);
+			if (url != null)
+				builder.deploymentURL(URI.create(url));
+		} else if (equalsOrSuffix(qName, "RoleName")) {
+			builder.roleName(currentOrNull(currentText));
+		} else if (equalsOrSuffix(qName, "InstanceName")) {
+			builder.instanceName(currentOrNull(currentText));
+		} else if (equalsOrSuffix(qName, "InstanceStatus")) {
+			String instanceStatus = currentOrNull(currentText);
+			if (instanceStatus != null)
+				builder.instanceStatus(InstanceStatus.fromValue(instanceStatus));
+		}  else if (equalsOrSuffix(qName, "InstanceStateDetails")) {
+			builder.instanceStateDetails(currentOrNull(currentText));
+		}  else if (equalsOrSuffix(qName, "InstanceErrorCode")) {
+			builder.instanceErrorCode(currentOrNull(currentText));
+		} else if (equalsOrSuffix(qName, "InstanceSize")) {
+			String instanceSize = currentOrNull(currentText);
+			if (instanceSize != null)
+				builder.instanceSize(RoleSize.fromValue(instanceSize));
+		} else if (equalsOrSuffix(qName, "IpAddress")) {
+			builder.privateIpAddress(currentOrNull(currentText));
+		} else if (equalsOrSuffix(qName, "Vip")) {
+			builder.publicIpAddress(currentOrNull(currentText));
+		}
+
+		currentText = new StringBuilder();
+		elements.remove(elements.size()-1);
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public void characters(char ch[], int start, int length) {
+		currentText.append(ch, start, length);
+	}
+
+}
diff --git a/labs/azure-management/src/main/java/org/jclouds/azure/management/xml/DetailedHostedServicePropertiesHandler.java b/labs/azure-management/src/main/java/org/jclouds/azure/management/xml/DetailedHostedServicePropertiesHandler.java
new file mode 100644
index 0000000..df3b9f5
--- /dev/null
+++ b/labs/azure-management/src/main/java/org/jclouds/azure/management/xml/DetailedHostedServicePropertiesHandler.java
@@ -0,0 +1,84 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.azure.management.xml;
+
+import static org.jclouds.util.SaxUtils.currentOrNull;
+import static org.jclouds.util.SaxUtils.equalsOrSuffix;
+
+import javax.inject.Inject;
+
+import org.jclouds.azure.management.domain.DetailedHostedServiceProperties;
+import org.jclouds.azure.management.domain.HostedService.Status;
+import org.jclouds.date.DateService;
+import org.xml.sax.SAXException;
+
+/**
+ * @see <a href="http://msdn.microsoft.com/en-us/library/gg441293" >api</a>
+ * @author Adrian Cole
+ */
+public class DetailedHostedServicePropertiesHandler extends HostedServicePropertiesHandler {
+
+   protected final DateService dateService;
+
+   @Inject
+   protected DetailedHostedServicePropertiesHandler(DateService dateService) {
+      this.dateService = dateService;
+   }
+
+   private DetailedHostedServiceProperties.Builder<?> builder = DetailedHostedServiceProperties.builder();
+
+   private String name;
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public DetailedHostedServiceProperties getResult() {
+      try {
+         return builder.fromHostedServiceProperties(super.getResult()).build();
+      } finally {
+         builder = DetailedHostedServiceProperties.builder();
+      }
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public void endElement(String uri, String name, String qName) throws SAXException {
+      if (equalsOrSuffix(qName, "DateCreated")) {
+         builder.created(dateService.iso8601SecondsDateParse(currentOrNull(currentText)));
+      } else if (equalsOrSuffix(qName, "DateLastModified")) {
+         builder.lastModified(dateService.iso8601SecondsDateParse(currentOrNull(currentText)));
+      } else if (equalsOrSuffix(qName, "Status")) {
+         String rawStatus = currentOrNull(currentText);
+         builder.rawStatus(rawStatus);
+         builder.status(Status.fromValue(rawStatus));
+      } else if (equalsOrSuffix(qName, "Name")) {
+         this.name = currentOrNull(currentText);
+      } else if (equalsOrSuffix(qName, "Value")) {
+         builder.addExtendedProperty(this.name, currentOrNull(currentText));
+         this.name = null;
+      } else {
+         super.endElement(uri, name, qName);
+      }
+      currentText = new StringBuilder();
+   }
+
+}
diff --git a/labs/azure-management/src/main/java/org/jclouds/azure/management/xml/DiskHandler.java b/labs/azure-management/src/main/java/org/jclouds/azure/management/xml/DiskHandler.java
new file mode 100644
index 0000000..c6c6523
--- /dev/null
+++ b/labs/azure-management/src/main/java/org/jclouds/azure/management/xml/DiskHandler.java
@@ -0,0 +1,122 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.azure.management.xml;
+
+import static org.jclouds.util.SaxUtils.currentOrNull;
+import static org.jclouds.util.SaxUtils.equalsOrSuffix;
+
+import java.net.URI;
+
+import javax.inject.Inject;
+
+import org.jclouds.azure.management.domain.Disk;
+import org.jclouds.azure.management.domain.OSType;
+import org.jclouds.http.functions.ParseSax;
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXException;
+
+/**
+ * @see <a href="http://msdn.microsoft.com/en-us/library/jj157176" >api</a>
+ * @author Adrian Cole
+ */
+public class DiskHandler extends
+		ParseSax.HandlerForGeneratedRequestWithResult<Disk> {
+
+	protected final AttachmentHandler attachmentHandler;
+
+	@Inject
+	protected DiskHandler(AttachmentHandler attachmentHandler) {
+		this.attachmentHandler = attachmentHandler;
+	}
+
+	protected StringBuilder currentText = new StringBuilder();
+	private Disk.Builder<?> builder = Disk.builder();
+
+	protected boolean inAttachment;
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public Disk getResult() {
+		try {
+			return builder.build();
+		} finally {
+			builder = Disk.builder();
+		}
+	}
+
+	@Override
+	public void startElement(String uri, String localName, String qName,
+			Attributes attributes) throws SAXException {
+		if (equalsOrSuffix(qName, "AttachedTo")) {
+			inAttachment = true;
+		}
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public void endElement(String uri, String name, String qName)
+			throws SAXException {
+		if (equalsOrSuffix(qName, "AttachedTo")) {
+			builder.attachedTo(attachmentHandler.getResult());
+			inAttachment = false;
+		} else if (inAttachment) {
+			attachmentHandler.endElement(uri, name, qName);
+		} else if (equalsOrSuffix(qName, "OS")) {
+			builder.os(OSType.fromValue(currentOrNull(currentText)));
+		} else if (equalsOrSuffix(qName, "Name")) {
+			builder.name(currentOrNull(currentText));
+		} else if (equalsOrSuffix(qName, "LogicalDiskSizeInGB")) {
+			String gb = currentOrNull(currentText);
+			if (gb != null)
+				builder.logicalSizeInGB(Integer.parseInt(gb));
+		} else if (equalsOrSuffix(qName, "Description")) {
+			builder.description(currentOrNull(currentText));
+		} else if (equalsOrSuffix(qName, "Location")) {
+			builder.location(currentOrNull(currentText));
+		} else if (equalsOrSuffix(qName, "AffinityGroup")) {
+			builder.affinityGroup(currentOrNull(currentText));
+		} else if (equalsOrSuffix(qName, "MediaLink")) {
+			String link = currentOrNull(currentText);
+			if (link != null)
+				builder.mediaLink(URI.create(link));
+		} else if (equalsOrSuffix(qName, "SourceImageName")) {
+			builder.sourceImage(currentOrNull(currentText));
+		} else if (equalsOrSuffix(qName, "Label")) {
+			builder.label(currentOrNull(currentText));
+		}
+		currentText = new StringBuilder();
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public void characters(char ch[], int start, int length) {
+		if (inAttachment) {
+			attachmentHandler.characters(ch, start, length);
+		} else {
+			currentText.append(ch, start, length);
+		}
+	}
+
+}
diff --git a/labs/azure-management/src/main/java/org/jclouds/azure/management/xml/ErrorHandler.java b/labs/azure-management/src/main/java/org/jclouds/azure/management/xml/ErrorHandler.java
new file mode 100644
index 0000000..1d5d360
--- /dev/null
+++ b/labs/azure-management/src/main/java/org/jclouds/azure/management/xml/ErrorHandler.java
@@ -0,0 +1,72 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.azure.management.xml;
+
+import org.jclouds.azure.management.domain.Error;
+import org.jclouds.azure.management.domain.Error.Code;
+import org.jclouds.http.functions.ParseSax;
+import org.jclouds.util.SaxUtils;
+import org.xml.sax.SAXException;
+
+/**
+ * @see <a href="http://msdn.microsoft.com/en-us/library/ee460801" >api</a>
+ * 
+ * @author Adrian Cole
+ */
+public class ErrorHandler extends ParseSax.HandlerForGeneratedRequestWithResult<Error> {
+
+   private StringBuilder currentText = new StringBuilder();
+   private Error.Builder builder = Error.builder();
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public Error getResult() {
+      try {
+         return builder.build();
+      } finally {
+         builder = Error.builder();
+      }
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public void endElement(String uri, String name, String qName) throws SAXException {
+      if (qName.equals("Code")) {
+         String rawCode = SaxUtils.currentOrNull(currentText);
+         builder.rawCode(rawCode);
+         builder.code(Code.fromValue(rawCode));
+      } else if (qName.equals("Message")) {
+         builder.message(SaxUtils.currentOrNull(currentText));
+      }
+      currentText = new StringBuilder();
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public void characters(char ch[], int start, int length) {
+      currentText.append(ch, start, length);
+   }
+
+}
diff --git a/labs/azure-management/src/main/java/org/jclouds/azure/management/xml/HostedServiceHandler.java b/labs/azure-management/src/main/java/org/jclouds/azure/management/xml/HostedServiceHandler.java
new file mode 100644
index 0000000..807813e
--- /dev/null
+++ b/labs/azure-management/src/main/java/org/jclouds/azure/management/xml/HostedServiceHandler.java
@@ -0,0 +1,112 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.azure.management.xml;
+
+import static org.jclouds.util.SaxUtils.currentOrNull;
+import static org.jclouds.util.SaxUtils.equalsOrSuffix;
+
+import java.net.URI;
+
+import javax.inject.Inject;
+
+import org.jclouds.azure.management.domain.HostedService;
+import org.jclouds.azure.management.domain.HostedService.Builder;
+import org.jclouds.http.functions.ParseSax;
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXException;
+
+/**
+ * @see <a href="http://msdn.microsoft.com/en-us/library/gg441293" >api</a>
+ * @author Adrian Cole
+ */
+public class HostedServiceHandler extends ParseSax.HandlerForGeneratedRequestWithResult<HostedService> {
+
+   protected final HostedServicePropertiesHandler hostedServicePropertiesHandler;
+
+   @Inject
+   protected HostedServiceHandler(HostedServicePropertiesHandler hostedServicePropertiesHandler) {
+      this.hostedServicePropertiesHandler = hostedServicePropertiesHandler;
+   }
+
+   protected StringBuilder currentText = new StringBuilder();
+   protected HostedService.Builder<?> builder = builder();
+
+   protected Builder<?> builder() {
+      return HostedService.builder();
+   }
+
+   protected boolean inHostedServiceProperties;
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public HostedService getResult() {
+      try {
+         return builder.build();
+      } finally {
+         builder = builder();
+      }
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public void startElement(String url, String name, String qName, Attributes attributes) throws SAXException {
+      if (equalsOrSuffix(qName, "HostedServiceProperties")) {
+         inHostedServiceProperties = true;
+      }
+      if (inHostedServiceProperties) {
+         hostedServicePropertiesHandler.startElement(url, name, qName, attributes);
+      }
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public void endElement(String uri, String name, String qName) throws SAXException {
+
+      if (equalsOrSuffix(qName, "HostedServiceProperties")) {
+         builder.properties(hostedServicePropertiesHandler.getResult());
+         inHostedServiceProperties = false;
+      } else if (inHostedServiceProperties) {
+         hostedServicePropertiesHandler.endElement(uri, name, qName);
+      } else if (equalsOrSuffix(qName, "Url")) {
+         builder.url(URI.create(currentOrNull(currentText)));
+      } else if (equalsOrSuffix(qName, "ServiceName")) {
+         builder.name(currentOrNull(currentText));
+      }
+      currentText = new StringBuilder();
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public void characters(char ch[], int start, int length) {
+      if (inHostedServiceProperties) {
+         hostedServicePropertiesHandler.characters(ch, start, length);
+      } else {
+         currentText.append(ch, start, length);
+      }
+   }
+
+}
diff --git a/labs/azure-management/src/main/java/org/jclouds/azure/management/xml/HostedServicePropertiesHandler.java b/labs/azure-management/src/main/java/org/jclouds/azure/management/xml/HostedServicePropertiesHandler.java
new file mode 100644
index 0000000..9652f1a
--- /dev/null
+++ b/labs/azure-management/src/main/java/org/jclouds/azure/management/xml/HostedServicePropertiesHandler.java
@@ -0,0 +1,76 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.azure.management.xml;
+
+import static org.jclouds.util.SaxUtils.currentOrNull;
+import static org.jclouds.util.SaxUtils.equalsOrSuffix;
+
+import org.jclouds.azure.management.domain.HostedServiceProperties;
+import org.jclouds.crypto.CryptoStreams;
+import org.jclouds.http.functions.ParseSax;
+import org.xml.sax.SAXException;
+
+/**
+ * @see <a href="http://msdn.microsoft.com/en-us/library/gg441293" >api</a>
+ * @author Adrian Cole
+ */
+public class HostedServicePropertiesHandler extends
+         ParseSax.HandlerForGeneratedRequestWithResult<HostedServiceProperties> {
+
+   protected StringBuilder currentText = new StringBuilder();
+   private HostedServiceProperties.Builder<?> builder = HostedServiceProperties.builder();
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public HostedServiceProperties getResult() {
+      try {
+         return builder.build();
+      } finally {
+         builder = HostedServiceProperties.builder();
+      }
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public void endElement(String uri, String name, String qName) throws SAXException {
+      if (equalsOrSuffix(qName, "Description")) {
+         builder.description(currentOrNull(currentText));
+      } else if (equalsOrSuffix(qName, "Location")) {
+         builder.location(currentOrNull(currentText));
+      } else if (equalsOrSuffix(qName, "AffinityGroup")) {
+         builder.affinityGroup(currentOrNull(currentText));
+      } else if (equalsOrSuffix(qName, "Label")) {
+         builder.label(new String(CryptoStreams.base64(currentOrNull(currentText))));
+      }
+      currentText = new StringBuilder();
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public void characters(char ch[], int start, int length) {
+      currentText.append(ch, start, length);
+   }
+
+}
diff --git a/labs/azure-management/src/main/java/org/jclouds/azure/management/xml/HostedServiceWithDetailedPropertiesHandler.java b/labs/azure-management/src/main/java/org/jclouds/azure/management/xml/HostedServiceWithDetailedPropertiesHandler.java
new file mode 100644
index 0000000..09cbfb7
--- /dev/null
+++ b/labs/azure-management/src/main/java/org/jclouds/azure/management/xml/HostedServiceWithDetailedPropertiesHandler.java
@@ -0,0 +1,32 @@
+package org.jclouds.azure.management.xml;
+
+import javax.inject.Inject;
+
+import org.jclouds.azure.management.domain.HostedServiceWithDetailedProperties;
+
+/**
+ * 
+ * @author Adrian Cole
+ */
+public class HostedServiceWithDetailedPropertiesHandler extends HostedServiceHandler {
+
+   @Inject
+   protected HostedServiceWithDetailedPropertiesHandler(
+            DetailedHostedServicePropertiesHandler hostedServicePropertiesHandler) {
+      super(hostedServicePropertiesHandler);
+   }
+
+   @Override
+   protected HostedServiceWithDetailedProperties.Builder<?> builder() {
+      return HostedServiceWithDetailedProperties.builder();
+   }
+
+   @Override
+   public HostedServiceWithDetailedProperties getResult() {
+      try {
+         return HostedServiceWithDetailedProperties.class.cast(builder.build());
+      } finally {
+         builder = builder();
+      }
+   }
+}
diff --git a/labs/azure-management/src/main/java/org/jclouds/azure/management/xml/ListDisksHandler.java b/labs/azure-management/src/main/java/org/jclouds/azure/management/xml/ListDisksHandler.java
new file mode 100644
index 0000000..591f2e9
--- /dev/null
+++ b/labs/azure-management/src/main/java/org/jclouds/azure/management/xml/ListDisksHandler.java
@@ -0,0 +1,93 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.azure.management.xml;
+
+import java.util.Set;
+
+import org.jclouds.azure.management.domain.Disk;
+import org.jclouds.http.functions.ParseSax;
+import org.jclouds.util.SaxUtils;
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXException;
+
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.ImmutableSet.Builder;
+import com.google.inject.Inject;
+
+/**
+ * @author Gerald Pereira
+ */
+public class ListDisksHandler extends ParseSax.HandlerForGeneratedRequestWithResult<Set<Disk>> {
+
+   private final DiskHandler diskHandler;
+
+   private Builder<Disk> disks = ImmutableSet.<Disk> builder();
+
+   private boolean inDisk;
+
+   @Inject
+   public ListDisksHandler(final DiskHandler diskHandler) {
+      this.diskHandler = diskHandler;
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public Set<Disk> getResult() {
+      return disks.build();
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public void startElement(String url, String name, String qName, Attributes attributes) throws SAXException {
+      if (SaxUtils.equalsOrSuffix(qName, "Disk")) {
+         inDisk = true;
+      }
+      if (inDisk) {
+         diskHandler.startElement(url, name, qName, attributes);
+      }
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public void endElement(String uri, String name, String qName) throws SAXException {
+      if (qName.equals("Disk")) {
+         inDisk = false;
+         disks.add(diskHandler.getResult());
+      } else if (inDisk) {
+         diskHandler.endElement(uri, name, qName);
+      }
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public void characters(char ch[], int start, int length) {
+      if (inDisk) {
+         diskHandler.characters(ch, start, length);
+      }
+   }
+
+}
diff --git a/labs/azure-management/src/main/java/org/jclouds/azure/management/xml/ListHostedServicesHandler.java b/labs/azure-management/src/main/java/org/jclouds/azure/management/xml/ListHostedServicesHandler.java
new file mode 100644
index 0000000..6c6ccff
--- /dev/null
+++ b/labs/azure-management/src/main/java/org/jclouds/azure/management/xml/ListHostedServicesHandler.java
@@ -0,0 +1,97 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.azure.management.xml;
+
+import java.util.Set;
+
+import org.jclouds.azure.management.domain.HostedServiceWithDetailedProperties;
+import org.jclouds.http.functions.ParseSax;
+import org.jclouds.util.SaxUtils;
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXException;
+
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.ImmutableSet.Builder;
+import com.google.inject.Inject;
+
+/**
+ * @see <a href="http://msdn.microsoft.com/en-us/library/ee460781">doc</a>
+ * 
+ * @author Adrian Cole
+ */
+public class ListHostedServicesHandler extends
+         ParseSax.HandlerForGeneratedRequestWithResult<Set<HostedServiceWithDetailedProperties>> {
+
+   private final HostedServiceWithDetailedPropertiesHandler hostedServiceHandler;
+
+   private Builder<HostedServiceWithDetailedProperties> hostedServices = ImmutableSet
+            .<HostedServiceWithDetailedProperties> builder();
+
+   private boolean inHostedService;
+
+   @Inject
+   public ListHostedServicesHandler(HostedServiceWithDetailedPropertiesHandler hostedServiceHandler) {
+      this.hostedServiceHandler = hostedServiceHandler;
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public Set<HostedServiceWithDetailedProperties> getResult() {
+      return hostedServices.build();
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public void startElement(String url, String name, String qName, Attributes attributes) throws SAXException {
+      if (SaxUtils.equalsOrSuffix(qName, "HostedService")) {
+         inHostedService = true;
+      }
+      if (inHostedService) {
+         hostedServiceHandler.startElement(url, name, qName, attributes);
+      }
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public void endElement(String uri, String name, String qName) throws SAXException {
+      if (qName.equals("HostedService")) {
+         inHostedService = false;
+         hostedServices.add(hostedServiceHandler.getResult());
+      } else if (inHostedService) {
+         hostedServiceHandler.endElement(uri, name, qName);
+      }
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public void characters(char ch[], int start, int length) {
+      if (inHostedService) {
+         hostedServiceHandler.characters(ch, start, length);
+      }
+   }
+
+}
diff --git a/labs/azure-management/src/main/java/org/jclouds/azure/management/xml/ListLocationsHandler.java b/labs/azure-management/src/main/java/org/jclouds/azure/management/xml/ListLocationsHandler.java
new file mode 100644
index 0000000..e2fe9a1
--- /dev/null
+++ b/labs/azure-management/src/main/java/org/jclouds/azure/management/xml/ListLocationsHandler.java
@@ -0,0 +1,93 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.azure.management.xml;
+
+import java.util.Set;
+
+import org.jclouds.azure.management.domain.Location;
+import org.jclouds.http.functions.ParseSax;
+import org.jclouds.util.SaxUtils;
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXException;
+
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.ImmutableSet.Builder;
+import com.google.inject.Inject;
+
+/**
+ * @author Adrian Cole
+ */
+public class ListLocationsHandler extends ParseSax.HandlerForGeneratedRequestWithResult<Set<Location>> {
+
+   private final LocationHandler locationHandler;
+
+   private Builder<Location> locations = ImmutableSet.<Location> builder();
+
+   private boolean inLocation;
+
+   @Inject
+   public ListLocationsHandler(LocationHandler locationHandler) {
+      this.locationHandler = locationHandler;
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public Set<Location> getResult() {
+      return locations.build();
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public void startElement(String url, String name, String qName, Attributes attributes) throws SAXException {
+      if (SaxUtils.equalsOrSuffix(qName, "Location")) {
+         inLocation = true;
+      }
+      if (inLocation) {
+         locationHandler.startElement(url, name, qName, attributes);
+      }
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public void endElement(String uri, String name, String qName) throws SAXException {
+      if (qName.equals("Location")) {
+         inLocation = false;
+         locations.add(locationHandler.getResult());
+      } else if (inLocation) {
+         locationHandler.endElement(uri, name, qName);
+      }
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public void characters(char ch[], int start, int length) {
+      if (inLocation) {
+         locationHandler.characters(ch, start, length);
+      }
+   }
+
+}
diff --git a/labs/azure-management/src/main/java/org/jclouds/azure/management/xml/ListOSImagesHandler.java b/labs/azure-management/src/main/java/org/jclouds/azure/management/xml/ListOSImagesHandler.java
new file mode 100644
index 0000000..471b2ff
--- /dev/null
+++ b/labs/azure-management/src/main/java/org/jclouds/azure/management/xml/ListOSImagesHandler.java
@@ -0,0 +1,93 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.azure.management.xml;
+
+import java.util.Set;
+
+import org.jclouds.azure.management.domain.OSImage;
+import org.jclouds.http.functions.ParseSax;
+import org.jclouds.util.SaxUtils;
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXException;
+
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.ImmutableSet.Builder;
+import com.google.inject.Inject;
+
+/**
+ * @author Adrian Cole
+ */
+public class ListOSImagesHandler extends ParseSax.HandlerForGeneratedRequestWithResult<Set<OSImage>> {
+
+   private final OSImageHandler locationHandler;
+
+   private Builder<OSImage> locations = ImmutableSet.<OSImage> builder();
+
+   private boolean inOSImage;
+
+   @Inject
+   public ListOSImagesHandler(OSImageHandler locationHandler) {
+      this.locationHandler = locationHandler;
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public Set<OSImage> getResult() {
+      return locations.build();
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public void startElement(String url, String name, String qName, Attributes attributes) throws SAXException {
+      if (SaxUtils.equalsOrSuffix(qName, "OSImage")) {
+         inOSImage = true;
+      }
+      if (inOSImage) {
+         locationHandler.startElement(url, name, qName, attributes);
+      }
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public void endElement(String uri, String name, String qName) throws SAXException {
+      if (qName.equals("OSImage")) {
+         inOSImage = false;
+         locations.add(locationHandler.getResult());
+      } else if (inOSImage) {
+         locationHandler.endElement(uri, name, qName);
+      }
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public void characters(char ch[], int start, int length) {
+      if (inOSImage) {
+         locationHandler.characters(ch, start, length);
+      }
+   }
+
+}
diff --git a/labs/azure-management/src/main/java/org/jclouds/azure/management/xml/LocationHandler.java b/labs/azure-management/src/main/java/org/jclouds/azure/management/xml/LocationHandler.java
new file mode 100644
index 0000000..34ee7aa
--- /dev/null
+++ b/labs/azure-management/src/main/java/org/jclouds/azure/management/xml/LocationHandler.java
@@ -0,0 +1,71 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.azure.management.xml;
+
+import org.jclouds.azure.management.domain.Location;
+import org.jclouds.http.functions.ParseSax;
+import org.jclouds.util.SaxUtils;
+import org.xml.sax.SAXException;
+
+/**
+ * @see <a href="http://msdn.microsoft.com/en-us/library/gg441293" >api</a>
+ * 
+ * @author Adrian Cole
+ */
+public class LocationHandler extends ParseSax.HandlerForGeneratedRequestWithResult<Location> {
+
+   private StringBuilder currentText = new StringBuilder();
+   private Location.Builder builder = Location.builder();
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public Location getResult() {
+      try {
+         return builder.build();
+      } finally {
+         builder = Location.builder();
+      }
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public void endElement(String uri, String name, String qName) throws SAXException {
+      if (qName.equals("Name")) {
+         builder.name(SaxUtils.currentOrNull(currentText));
+      } else if (qName.equals("DisplayName")) {
+         builder.displayName(SaxUtils.currentOrNull(currentText));
+      } else if (qName.equals("AvailableService")) {
+         builder.addAvailableService(SaxUtils.currentOrNull(currentText));
+      }
+      currentText = new StringBuilder();
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public void characters(char ch[], int start, int length) {
+      currentText.append(ch, start, length);
+   }
+
+}
diff --git a/labs/azure-management/src/main/java/org/jclouds/azure/management/xml/OSImageHandler.java b/labs/azure-management/src/main/java/org/jclouds/azure/management/xml/OSImageHandler.java
new file mode 100644
index 0000000..dae17df
--- /dev/null
+++ b/labs/azure-management/src/main/java/org/jclouds/azure/management/xml/OSImageHandler.java
@@ -0,0 +1,95 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.azure.management.xml;
+
+import static org.jclouds.util.SaxUtils.currentOrNull;
+import static org.jclouds.util.SaxUtils.equalsOrSuffix;
+
+import java.net.URI;
+
+import org.jclouds.azure.management.domain.OSImage;
+import org.jclouds.azure.management.domain.OSType;
+import org.jclouds.http.functions.ParseSax;
+import org.xml.sax.SAXException;
+
+/**
+ * @see <a href="http://msdn.microsoft.com/en-us/library/jj157191" >api</a>
+ * @author Adrian Cole
+ */
+public class OSImageHandler extends ParseSax.HandlerForGeneratedRequestWithResult<OSImage> {
+
+   protected StringBuilder currentText = new StringBuilder();
+   private OSImage.Builder<?> builder = OSImage.builder();
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public OSImage getResult() {
+      try {
+         return builder.build();
+      } finally {
+         builder = OSImage.builder();
+      }
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public void endElement(String uri, String name, String qName) throws SAXException {
+      if (equalsOrSuffix(qName, "OS")) {
+         builder.os(OSType.fromValue(currentOrNull(currentText)));
+      } else if (equalsOrSuffix(qName, "Name")) {
+         builder.name(currentOrNull(currentText));
+      } else if (equalsOrSuffix(qName, "LogicalSizeInGB")) {
+         String gb = currentOrNull(currentText);
+         if (gb != null)
+            builder.logicalSizeInGB(Integer.parseInt(gb));
+      } else if (equalsOrSuffix(qName, "Description")) {
+         builder.description(currentOrNull(currentText));
+      } else if (equalsOrSuffix(qName, "Category")) {
+         builder.category(currentOrNull(currentText));
+      } else if (equalsOrSuffix(qName, "Location")) {
+         builder.location(currentOrNull(currentText));
+      } else if (equalsOrSuffix(qName, "AffinityGroup")) {
+         builder.affinityGroup(currentOrNull(currentText));
+      } else if (equalsOrSuffix(qName, "MediaLink")) {
+         String link = currentOrNull(currentText);
+         if (link != null)
+            builder.mediaLink(URI.create(link));
+      } else if (equalsOrSuffix(qName, "Eula")) {
+         String eula = currentOrNull(currentText);
+         if (eula != null)
+            builder.eula(URI.create(eula));
+      } else if (equalsOrSuffix(qName, "Label")) {
+         builder.label(currentOrNull(currentText));
+      }
+      currentText = new StringBuilder();
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public void characters(char ch[], int start, int length) {
+      currentText.append(ch, start, length);
+   }
+
+}
diff --git a/labs/azure-management/src/main/java/org/jclouds/azure/management/xml/OperationHandler.java b/labs/azure-management/src/main/java/org/jclouds/azure/management/xml/OperationHandler.java
new file mode 100644
index 0000000..98efb3c
--- /dev/null
+++ b/labs/azure-management/src/main/java/org/jclouds/azure/management/xml/OperationHandler.java
@@ -0,0 +1,114 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.azure.management.xml;
+
+import static org.jclouds.util.SaxUtils.currentOrNull;
+import static org.jclouds.util.SaxUtils.equalsOrSuffix;
+
+import javax.inject.Inject;
+
+import org.jclouds.azure.management.domain.Operation;
+import org.jclouds.azure.management.domain.Operation.Builder;
+import org.jclouds.azure.management.domain.Operation.Status;
+import org.jclouds.http.functions.ParseSax;
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXException;
+
+/**
+ * @see <a href="http://msdn.microsoft.com/en-us/library/ee460783" >api</a>
+ * @author Adrian Cole
+ */
+public class OperationHandler extends ParseSax.HandlerForGeneratedRequestWithResult<Operation> {
+
+   protected final ErrorHandler errorHandler;
+
+   @Inject
+   protected OperationHandler(ErrorHandler errorHandler) {
+      this.errorHandler = errorHandler;
+   }
+
+   protected StringBuilder currentText = new StringBuilder();
+   protected Operation.Builder builder = builder();
+
+   protected Builder builder() {
+      return Operation.builder();
+   }
+
+   protected boolean inError;
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public Operation getResult() {
+      try {
+         return builder.build();
+      } finally {
+         builder = builder();
+      }
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public void startElement(String url, String name, String qName, Attributes attributes) throws SAXException {
+      if (equalsOrSuffix(qName, "Error")) {
+         inError = true;
+      }
+      if (inError) {
+         errorHandler.startElement(url, name, qName, attributes);
+      }
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public void endElement(String uri, String name, String qName) throws SAXException {
+      if (equalsOrSuffix(qName, "Error")) {
+         builder.error(errorHandler.getResult());
+         inError = false;
+      } else if (inError) {
+         errorHandler.endElement(uri, name, qName);
+      } else if (equalsOrSuffix(qName, "ID")) {
+         builder.id(currentOrNull(currentText));
+      } else if (qName.equals("Status")) {
+         String rawStatus = currentOrNull(currentText);
+         builder.rawStatus(rawStatus);
+         builder.status(Status.fromValue(rawStatus));
+      } else if (equalsOrSuffix(qName, "HttpStatusCode")) {
+         builder.httpStatusCode(Integer.parseInt(currentOrNull(currentText)));
+      }
+      currentText = new StringBuilder();
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public void characters(char ch[], int start, int length) {
+      if (inError) {
+         errorHandler.characters(ch, start, length);
+      } else {
+         currentText.append(ch, start, length);
+      }
+   }
+
+}
diff --git a/labs/azure-management/src/main/resources/META-INF/services/org.jclouds.providers.ProviderMetadata b/labs/azure-management/src/main/resources/META-INF/services/org.jclouds.providers.ProviderMetadata
new file mode 100644
index 0000000..03fb1db
--- /dev/null
+++ b/labs/azure-management/src/main/resources/META-INF/services/org.jclouds.providers.ProviderMetadata
@@ -0,0 +1 @@
+org.jclouds.azure.management.AzureManagementProviderMetadata
diff --git a/labs/azure-management/src/test/java/org/jclouds/azure/management/AzureManagementProviderMetadataTest.java b/labs/azure-management/src/test/java/org/jclouds/azure/management/AzureManagementProviderMetadataTest.java
new file mode 100644
index 0000000..dda5408
--- /dev/null
+++ b/labs/azure-management/src/test/java/org/jclouds/azure/management/AzureManagementProviderMetadataTest.java
@@ -0,0 +1,34 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not computee 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.azure.management;
+
+import org.jclouds.providers.internal.BaseProviderMetadataTest;
+import org.testng.annotations.Test;
+
+/**
+ * 
+ * @author Adrian Cole
+ */
+@Test(groups = "unit", testName = "AzureManagementProviderMetadataTest")
+public class AzureManagementProviderMetadataTest extends BaseProviderMetadataTest {
+
+   public AzureManagementProviderMetadataTest() {
+      super(new AzureManagementProviderMetadata(), new AzureManagementApiMetadata());
+   }
+}
diff --git a/labs/azure-management/src/test/java/org/jclouds/azure/management/features/DiskApiExpectTest.java b/labs/azure-management/src/test/java/org/jclouds/azure/management/features/DiskApiExpectTest.java
new file mode 100644
index 0000000..b99923b
--- /dev/null
+++ b/labs/azure-management/src/test/java/org/jclouds/azure/management/features/DiskApiExpectTest.java
@@ -0,0 +1,86 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unles 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 expres or implied.  See the License for the
+ * specific language governing permisions and limitations
+ * under the License.
+ */
+package org.jclouds.azure.management.features;
+
+import static org.testng.Assert.assertEquals;
+
+import org.jclouds.azure.management.AzureManagementApi;
+import org.jclouds.azure.management.internal.BaseAzureManagementApiExpectTest;
+import org.jclouds.azure.management.parse.ListDisksTest;
+import org.jclouds.http.HttpRequest;
+import org.jclouds.http.HttpResponse;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.ImmutableSet;
+
+/**
+ * @author Gérald Pereira
+ */
+@Test(groups = "unit", testName = "DiskApiExpectTest")
+public class DiskApiExpectTest extends BaseAzureManagementApiExpectTest {
+
+	private final static String DISK_NAME = "mydisk";
+	
+   HttpRequest list = HttpRequest.builder().method("GET")
+                                 .endpoint("https://management.core.windows.net/" + subscriptionId + "/services/disks")
+                                 .addHeader("x-ms-version", "2012-03-01")
+                                 .addHeader("Accept", "application/xml").build();
+   
+   public void testListWhenResponseIs2xx() throws Exception {
+
+      HttpResponse listResponse = HttpResponse.builder().statusCode(200)
+            .payload(payloadFromResourceWithContentType("/disks.xml", "application/xml")).build();
+
+      AzureManagementApi apiWhenExist = requestSendsResponse(
+            list, listResponse);
+
+      assertEquals(apiWhenExist.getDiskApi().list().toString(), new ListDisksTest().expected().toString());
+   }
+
+   public void testListWhenResponseIs404() throws Exception {
+
+      HttpResponse listResponse = HttpResponse.builder().statusCode(404).build();
+
+      AzureManagementApi apiWhenDontExist = requestSendsResponse(
+            list, listResponse);
+
+      assertEquals(apiWhenDontExist.getDiskApi().list(), ImmutableSet.of());
+   }
+
+   HttpRequest delete = HttpRequest.builder().method("DELETE")
+            .endpoint("https://management.core.windows.net/" + subscriptionId + "/services/disks/" + DISK_NAME)
+            .addHeader("x-ms-version", "2012-03-01")
+            .build();
+   
+   public void testDeleteWhenResponseIs2xx() throws Exception {
+      HttpResponse deleteResponse = HttpResponse.builder().statusCode(200).addHeader("x-ms-request-id", "fakerequestid").build();
+
+      AzureManagementApi apiWhenExist = requestSendsResponse(delete, deleteResponse);
+
+      apiWhenExist.getDiskApi().delete(DISK_NAME);
+   }
+
+   public void testDeleteWhenResponseIs404() throws Exception {
+      HttpResponse deleteResponse = HttpResponse.builder().statusCode(404).build();
+
+      AzureManagementApi apiWhenDontExist = requestSendsResponse(delete, deleteResponse);
+
+      apiWhenDontExist.getDiskApi().delete(DISK_NAME);
+   }
+}
diff --git a/labs/azure-management/src/test/java/org/jclouds/azure/management/features/DiskApiLiveTest.java b/labs/azure-management/src/test/java/org/jclouds/azure/management/features/DiskApiLiveTest.java
new file mode 100644
index 0000000..4055c01
--- /dev/null
+++ b/labs/azure-management/src/test/java/org/jclouds/azure/management/features/DiskApiLiveTest.java
@@ -0,0 +1,127 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.azure.management.features;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.collect.Iterables.transform;
+import static org.testng.Assert.assertNotEquals;
+import static org.testng.Assert.assertTrue;
+
+import java.util.Set;
+
+import org.jclouds.azure.management.domain.Disk;
+import org.jclouds.azure.management.domain.Location;
+import org.jclouds.azure.management.domain.OSImage;
+import org.jclouds.azure.management.domain.OSType;
+import org.jclouds.azure.management.internal.BaseAzureManagementApiLiveTest;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import com.google.common.base.Function;
+import com.google.common.collect.ImmutableSet;
+
+/**
+ * @author Adrian Cole
+ */
+@Test(groups = "live", testName = "DiskApiLiveTest")
+public class DiskApiLiveTest extends BaseAzureManagementApiLiveTest {
+
+   private ImmutableSet<String> locations;
+   private ImmutableSet<String> images;
+
+   @BeforeClass(groups = { "integration", "live" })
+   public void setupContext() {
+      super.initializeContext();
+
+      locations = ImmutableSet.copyOf(transform(context.getApi().getLocationApi().list(),
+               new Function<Location, String>() {
+                  @Override
+                  public String apply(Location in) {
+                     return in.getName();
+                  }
+               }));
+      images = ImmutableSet.copyOf(transform(context.getApi().getOSImageApi().list(), new Function<OSImage, String>() {
+         @Override
+         public String apply(OSImage in) {
+            return in.getName();
+         }
+      }));
+   }
+
+   @Test
+   protected void testList() {
+      Set<Disk> response = api().list();
+
+      for (Disk disk : response) {
+         checkDisk(disk);
+      }
+   }
+
+   private void checkDisk(Disk disk) {
+      checkNotNull(disk.getName(), "Name cannot be null for Disk %s", disk.getLabel());
+      checkNotNull(disk.getOS(), "OS cannot be null for Disk: %s", disk);
+      assertNotEquals(disk.getOS(), OSType.UNRECOGNIZED, "Status cannot be UNRECOGNIZED for Disk: " + disk);
+
+      checkNotNull(disk.getAttachedTo(), "While AttachedTo can be null for Disk, its Optional wrapper cannot: %s", disk);
+      if (disk.getAttachedTo().isPresent()) {
+         // TODO: verify you can lookup the role
+      }
+
+      checkNotNull(disk.getLogicalSizeInGB(),
+               "While LogicalSizeInGB can be null for Disk, its Optional wrapper cannot: %s", disk);
+
+      if (disk.getLogicalSizeInGB().isPresent())
+         assertTrue(disk.getLogicalSizeInGB().get() > 0, "LogicalSizeInGB should be positive, if set" + disk.toString());
+
+      checkNotNull(disk.getMediaLink(), "While MediaLink can be null for Disk, its Optional wrapper cannot: %s", disk);
+
+      if (disk.getMediaLink().isPresent())
+         assertTrue(ImmutableSet.of("http", "https").contains(disk.getMediaLink().get().getScheme()),
+                  "MediaLink should be an http(s) url" + disk.toString());
+      
+      checkNotNull(disk.getLabel(), "While Label can be null for Disk, its Optional wrapper cannot: %s",
+               disk);
+      
+      checkNotNull(disk.getDescription(), "While Description can be null for Disk, its Optional wrapper cannot: %s",
+               disk);
+
+      checkNotNull(disk.getLocation(), "While Location can be null for Disk, its Optional wrapper cannot: %s", disk);
+      if (disk.getLocation().isPresent()) {
+         assertTrue(locations.contains(disk.getLocation().get()),
+                  "Location not in " + locations + " :" + disk.toString());
+      }
+
+      checkNotNull(disk.getSourceImage(), "While SourceImage can be null for Disk, its Optional wrapper cannot: %s",
+               disk);
+      if (disk.getSourceImage().isPresent()) {
+         assertTrue(images.contains(disk.getSourceImage().get()),
+                  "SourceImage not in " + images + " :" + disk.toString());
+      }
+
+      checkNotNull(disk.getAffinityGroup(),
+               "While AffinityGroup can be null for Disk, its Optional wrapper cannot: %s", disk);
+      if (disk.getAffinityGroup().isPresent()) {
+         // TODO: list getAffinityGroups and check if there
+      }
+   }
+
+   protected DiskApi api() {
+      return context.getApi().getDiskApi();
+   }
+}
diff --git a/labs/azure-management/src/test/java/org/jclouds/azure/management/features/HostedServiceApiExpectTest.java b/labs/azure-management/src/test/java/org/jclouds/azure/management/features/HostedServiceApiExpectTest.java
new file mode 100644
index 0000000..2c35936
--- /dev/null
+++ b/labs/azure-management/src/test/java/org/jclouds/azure/management/features/HostedServiceApiExpectTest.java
@@ -0,0 +1,173 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unles 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 expres or implied.  See the License for the
+ * specific language governing permisions and limitations
+ * under the License.
+ */
+package org.jclouds.azure.management.features;
+
+import static org.jclouds.azure.management.options.CreateHostedServiceOptions.Builder.description;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNull;
+
+import org.jclouds.azure.management.AzureManagementApi;
+import org.jclouds.azure.management.internal.BaseAzureManagementApiExpectTest;
+import org.jclouds.azure.management.parse.GetHostedServiceDetailsTest;
+import org.jclouds.azure.management.parse.GetHostedServiceTest;
+import org.jclouds.azure.management.parse.ListHostedServicesTest;
+import org.jclouds.http.HttpRequest;
+import org.jclouds.http.HttpResponse;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+
+/**
+ * @author Adrian Cole
+ */
+@Test(groups = "unit", testName = "HostedServiceApiExpectTest")
+public class HostedServiceApiExpectTest extends BaseAzureManagementApiExpectTest {
+
+   private static final String SERVICE_NAME = "myservice";
+   HttpRequest list = HttpRequest.builder().method("GET")
+                                 .endpoint("https://management.core.windows.net/" + subscriptionId + "/services/hostedservices")
+                                 .addHeader("x-ms-version", "2012-03-01")
+                                 .addHeader("Accept", "application/xml").build();
+   
+   public void testListWhenResponseIs2xx() throws Exception {
+
+      HttpResponse listResponse = HttpResponse.builder().statusCode(200)
+            .payload(payloadFromResourceWithContentType("/hostedservices.xml", "application")).build();
+
+      AzureManagementApi apiWhenExist = requestSendsResponse(
+            list, listResponse);
+
+      assertEquals(apiWhenExist.getHostedServiceApi().list().toString(), new ListHostedServicesTest().expected().toString());
+   }
+
+   public void testListWhenResponseIs404() throws Exception {
+
+      HttpResponse listResponse = HttpResponse.builder().statusCode(404).build();
+
+      AzureManagementApi apiWhenDontExist = requestSendsResponse(
+            list, listResponse);
+
+      assertEquals(apiWhenDontExist.getHostedServiceApi().list(), ImmutableSet.of());
+   }
+   
+
+   public void testCreateServiceWithLabelInLocationWhenResponseIs2xx() throws Exception {
+      HttpRequest create = HttpRequest.builder().method("POST")
+                                      .endpoint("https://management.core.windows.net/" + subscriptionId + "/services/hostedservices")
+                                      .addHeader("x-ms-version", "2012-03-01")
+                                      .payload(payloadFromResourceWithContentType("/create_hostedservice_location.xml", "application/xml")).build();
+            
+      HttpResponse createResponse = HttpResponse.builder()
+                                                .addHeader("x-ms-request-id", "171f77920784404db208200702e59227")
+                                                .statusCode(201).build();
+
+      AzureManagementApi apiWhenExist = requestSendsResponse(create, createResponse);
+
+      assertEquals(
+               apiWhenExist.getHostedServiceApi().createServiceWithLabelInLocation(SERVICE_NAME, "service mine",
+                        "West US"), "171f77920784404db208200702e59227");
+   }
+
+   public void testCreateWithOptionalParamsWhenResponseIs2xx() throws Exception {
+      HttpRequest create = HttpRequest.builder().method("POST")
+               .endpoint("https://management.core.windows.net/" + subscriptionId + "/services/hostedservices")
+               .addHeader("x-ms-version", "2012-03-01")
+               .payload(payloadFromResourceWithContentType("/create_hostedservice_location_options.xml", "application/xml")).build();
+
+      HttpResponse createResponse = HttpResponse.builder()
+                                                .addHeader("x-ms-request-id", "171f77920784404db208200702e59227")
+                                                .statusCode(201).build();
+      
+      AzureManagementApi apiWhenExist = requestSendsResponse(create, createResponse);
+      
+      assertEquals(
+               apiWhenExist.getHostedServiceApi().createServiceWithLabelInLocation(SERVICE_NAME, "service mine",
+                        "West US",
+                        description("my description").extendedProperties(ImmutableMap.of("Role", "Production"))),
+               "171f77920784404db208200702e59227");
+   }
+   
+   HttpRequest get = HttpRequest.builder().method("GET")
+            .endpoint("https://management.core.windows.net/" + subscriptionId + "/services/hostedservices/" + SERVICE_NAME)
+            .addHeader("x-ms-version", "2012-03-01")
+            .addHeader("Accept", "application/xml").build();
+   
+   public void testGetWhenResponseIs2xx() throws Exception {
+      HttpResponse getResponse = HttpResponse.builder().statusCode(200)
+               .payload(payloadFromResourceWithContentType("/hostedservice.xml", "application")).build();
+
+      AzureManagementApi apiWhenExist = requestSendsResponse(get, getResponse);
+
+      assertEquals(apiWhenExist.getHostedServiceApi().get(SERVICE_NAME).toString(), new GetHostedServiceTest().expected().toString());
+   }
+
+   public void testGetWhenResponseIs404() throws Exception {
+      HttpResponse getResponse = HttpResponse.builder().statusCode(404).build();
+
+      AzureManagementApi apiWhenDontExist = requestSendsResponse(get, getResponse);
+
+      assertNull(apiWhenDontExist.getHostedServiceApi().get(SERVICE_NAME));
+   }
+   
+   HttpRequest getDetails = HttpRequest.builder().method("GET")
+            .endpoint("https://management.core.windows.net/" + subscriptionId + "/services/hostedservices/" + SERVICE_NAME + "?embed-detail=true")
+            .addHeader("x-ms-version", "2012-03-01")
+            .addHeader("Accept", "application/xml").build();
+   
+   public void testGetDetailsWhenResponseIs2xx() throws Exception {
+      HttpResponse getResponse = HttpResponse.builder().statusCode(200)
+               .payload(payloadFromResourceWithContentType("/hostedservice_details.xml", "application")).build();
+
+      AzureManagementApi apiWhenExist = requestSendsResponse(getDetails, getResponse);
+
+      assertEquals(apiWhenExist.getHostedServiceApi().getDetails(SERVICE_NAME).toString(), new GetHostedServiceDetailsTest().expected().toString());
+   }
+
+   public void testGetDetailsWhenResponseIs404() throws Exception {
+      HttpResponse getResponse = HttpResponse.builder().statusCode(404).build();
+
+      AzureManagementApi apiWhenDontExist = requestSendsResponse(getDetails, getResponse);
+
+      assertNull(apiWhenDontExist.getHostedServiceApi().getDetails(SERVICE_NAME));
+   }
+   
+   HttpRequest delete = HttpRequest.builder().method("DELETE")
+            .endpoint("https://management.core.windows.net/" + subscriptionId + "/services/hostedservices/" + SERVICE_NAME)
+            .addHeader("x-ms-version", "2012-03-01")
+            .build();
+   
+   public void testDeleteWhenResponseIs2xx() throws Exception {
+      HttpResponse deleteResponse = HttpResponse.builder()
+                                                .addHeader("x-ms-request-id", "171f77920784404db208200702e59227")
+                                                .statusCode(200).build();
+
+      AzureManagementApi apiWhenExist = requestSendsResponse(delete, deleteResponse);
+
+      assertEquals(apiWhenExist.getHostedServiceApi().delete(SERVICE_NAME), "171f77920784404db208200702e59227");
+   }
+
+   public void testDeleteWhenResponseIs404() throws Exception {
+      HttpResponse deleteResponse = HttpResponse.builder().statusCode(404).build();
+
+      AzureManagementApi apiWhenDontExist = requestSendsResponse(delete, deleteResponse);
+
+      assertNull(apiWhenDontExist.getHostedServiceApi().delete(SERVICE_NAME));
+   }
+}
diff --git a/labs/azure-management/src/test/java/org/jclouds/azure/management/features/HostedServiceApiLiveTest.java b/labs/azure-management/src/test/java/org/jclouds/azure/management/features/HostedServiceApiLiveTest.java
new file mode 100644
index 0000000..8e5db20
--- /dev/null
+++ b/labs/azure-management/src/test/java/org/jclouds/azure/management/features/HostedServiceApiLiveTest.java
@@ -0,0 +1,188 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.azure.management.features;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Preconditions.checkState;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotEquals;
+import static org.testng.Assert.assertTrue;
+
+import java.util.Set;
+import java.util.concurrent.TimeUnit;
+import java.util.logging.Logger;
+
+import org.jclouds.azure.management.domain.DetailedHostedServiceProperties;
+import org.jclouds.azure.management.domain.HostedService;
+import org.jclouds.azure.management.domain.HostedService.Status;
+import org.jclouds.azure.management.domain.HostedServiceWithDetailedProperties;
+import org.jclouds.azure.management.domain.Operation;
+import org.jclouds.azure.management.internal.BaseAzureManagementApiLiveTest;
+import org.jclouds.predicates.RetryablePredicate;
+import org.testng.Assert;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import com.google.common.base.Predicate;
+import com.google.common.collect.Iterables;
+
+/**
+ * @author Adrian Cole
+ */
+@Test(groups = "live", testName = "HostedServiceApiLiveTest")
+public class HostedServiceApiLiveTest extends BaseAzureManagementApiLiveTest {
+
+   public static final String HOSTED_SERVICE = (System.getProperty("user.name") + "-jclouds-hostedService")
+            .toLowerCase();
+
+   private RetryablePredicate<String> operationSucceeded;
+   private RetryablePredicate<HostedServiceWithDetailedProperties> hostedServiceCreated;
+   private RetryablePredicate<HostedService> hostedServiceGone;
+
+   private String location;
+
+   @BeforeClass(groups = "live")
+   @Override
+   public void setupContext() {
+      super.setupContext();
+      // TODO: filter locations on those who have compute
+      location = Iterables.get(context.getApi().getLocationApi().list(), 0).getName();
+      operationSucceeded = new RetryablePredicate<String>(new Predicate<String>() {
+
+         @Override
+         public boolean apply(String input) {
+            return context.getApi().getOperationApi().get(input).getStatus() == Operation.Status.SUCCEEDED;
+         }
+
+      }, 600, 5, 5, TimeUnit.SECONDS);
+
+      hostedServiceCreated = new RetryablePredicate<HostedServiceWithDetailedProperties>(
+               new Predicate<HostedServiceWithDetailedProperties>() {
+
+                  @Override
+                  public boolean apply(HostedServiceWithDetailedProperties input) {
+                     return api().getDetails(input.getName()).getProperties().getStatus() == Status.CREATED;
+                  }
+
+               }, 600, 5, 5, TimeUnit.SECONDS);
+
+      hostedServiceGone = new RetryablePredicate<HostedService>(new Predicate<HostedService>() {
+
+         @Override
+         public boolean apply(HostedService input) {
+            return api().get(input.getName()) == null;
+         }
+
+      }, 600, 5, 5, TimeUnit.SECONDS);
+   }
+
+   private HostedServiceWithDetailedProperties hostedService;
+
+   public void testCreateHostedService() {
+
+      String requestId = api().createServiceWithLabelInLocation(HOSTED_SERVICE, HOSTED_SERVICE, location);
+      assertTrue(operationSucceeded.apply(requestId), requestId);
+      Logger.getAnonymousLogger().info("operation succeeded: " + requestId);
+
+      hostedService = api().getDetails(HOSTED_SERVICE);
+      Logger.getAnonymousLogger().info("created hostedService: " + hostedService);
+
+      assertEquals(hostedService.getName(), HOSTED_SERVICE);
+
+      checkHostedService(hostedService);
+
+      assertTrue(hostedServiceCreated.apply(hostedService), hostedService.toString());
+      hostedService = api().getDetails(hostedService.getName());
+      Logger.getAnonymousLogger().info("hostedService available: " + hostedService);
+
+   }
+
+   @Test(dependsOnMethods = "testCreateHostedService")
+   public void testDeleteHostedService() {
+      String requestId = api().delete(hostedService.getName());
+      assertTrue(operationSucceeded.apply(requestId), requestId);
+      Logger.getAnonymousLogger().info("operation succeeded: " + requestId);
+
+      assertTrue(hostedServiceGone.apply(hostedService), hostedService.toString());
+      Logger.getAnonymousLogger().info("hostedService deleted: " + hostedService);
+   }
+
+   @Override
+   @AfterClass(groups = "live")
+   protected void tearDownContext() {
+      String requestId = api().delete(HOSTED_SERVICE);
+      if (requestId != null)
+         operationSucceeded.apply(requestId);
+
+      super.tearDownContext();
+   }
+
+   @Test
+   protected void testList() {
+      Set<HostedServiceWithDetailedProperties> response = api().list();
+
+      for (HostedServiceWithDetailedProperties hostedService : response) {
+         checkHostedService(hostedService);
+      }
+
+      if (response.size() > 0) {
+         HostedService hostedService = response.iterator().next();
+         Assert.assertEquals(api().getDetails(hostedService.getName()), hostedService);
+      }
+   }
+
+   private void checkHostedService(HostedServiceWithDetailedProperties hostedService) {
+      checkNotNull(hostedService.getUrl(), "Url cannot be null for a HostedService.");
+      checkNotNull(hostedService.getName(), "ServiceName cannot be null for HostedService %s", hostedService.getUrl());
+      checkNotNull(hostedService.getProperties(), "Properties cannot be null for HostedService %s",
+               hostedService.getUrl());
+      checkProperties(hostedService.getProperties());
+   }
+
+   private void checkProperties(DetailedHostedServiceProperties hostedService) {
+      checkNotNull(hostedService.getDescription(),
+               "While Description can be null for DetailedHostedServiceProperties, its Optional wrapper cannot: %s",
+               hostedService);
+      checkNotNull(hostedService.getLocation(),
+               "While Location can be null for DetailedHostedServiceProperties, its Optional wrapper cannot: %s",
+               hostedService);
+      checkNotNull(hostedService.getAffinityGroup(),
+               "While AffinityGroup can be null for DetailedHostedServiceProperties, its Optional wrapper cannot: %s",
+               hostedService);
+      checkState(hostedService.getLocation().isPresent() || hostedService.getAffinityGroup().isPresent(),
+               "Location or AffinityGroup must be present for DetailedHostedServiceProperties: %s", hostedService);
+      checkNotNull(hostedService.getLabel(), "Label cannot be null for HostedService %s", hostedService);
+
+      checkNotNull(hostedService.getStatus(), "Status cannot be null for DetailedHostedServiceProperties: %s",
+               hostedService);
+      assertNotEquals(hostedService.getStatus(), Status.UNRECOGNIZED,
+               "Status cannot be UNRECOGNIZED for DetailedHostedServiceProperties: " + hostedService);
+      checkNotNull(hostedService.getCreated(), "Created cannot be null for DetailedHostedServiceProperties %s",
+               hostedService);
+      checkNotNull(hostedService.getLastModified(),
+               "LastModified cannot be null for DetailedHostedServiceProperties %s", hostedService);
+      checkNotNull(hostedService.getExtendedProperties(),
+               "ExtendedProperties cannot be null for DetailedHostedServiceProperties %s", hostedService);
+   }
+
+   protected HostedServiceApi api() {
+      return context.getApi().getHostedServiceApi();
+   }
+}
diff --git a/labs/azure-management/src/test/java/org/jclouds/azure/management/features/LocationApiExpectTest.java b/labs/azure-management/src/test/java/org/jclouds/azure/management/features/LocationApiExpectTest.java
new file mode 100644
index 0000000..6ec2ff5
--- /dev/null
+++ b/labs/azure-management/src/test/java/org/jclouds/azure/management/features/LocationApiExpectTest.java
@@ -0,0 +1,64 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unles 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 expres or implied.  See the License for the
+ * specific language governing permisions and limitations
+ * under the License.
+ */
+package org.jclouds.azure.management.features;
+
+import static org.testng.Assert.assertEquals;
+
+import org.jclouds.azure.management.AzureManagementApi;
+import org.jclouds.azure.management.internal.BaseAzureManagementApiExpectTest;
+import org.jclouds.azure.management.parse.ListLocationsTest;
+import org.jclouds.http.HttpRequest;
+import org.jclouds.http.HttpResponse;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.ImmutableSet;
+
+/**
+ * @author Adrian Cole
+ */
+@Test(groups = "unit", testName = "LocationApiExpectTest")
+public class LocationApiExpectTest extends BaseAzureManagementApiExpectTest {
+
+   HttpRequest list = HttpRequest.builder()
+                                 .method("GET")
+                                 .endpoint("https://management.core.windows.net/" + subscriptionId + "/locations")
+                                 .addHeader("x-ms-version", "2012-03-01")
+                                 .addHeader("Accept", "application/xml").build();
+   
+   public void testListWhenResponseIs2xx() throws Exception {
+
+      HttpResponse listResponse = HttpResponse.builder().statusCode(200)
+            .payload(payloadFromResourceWithContentType("/locations.xml", "application")).build();
+
+      AzureManagementApi apiWhenExist = requestSendsResponse(
+            list, listResponse);
+
+      assertEquals(apiWhenExist.getLocationApi().list().toString(), new ListLocationsTest().expected().toString());
+   }
+
+   public void testListWhenResponseIs404() throws Exception {
+
+      HttpResponse listResponse = HttpResponse.builder().statusCode(404).build();
+
+      AzureManagementApi apiWhenDontExist = requestSendsResponse(
+            list, listResponse);
+
+      assertEquals(apiWhenDontExist.getLocationApi().list(), ImmutableSet.of());
+   }
+}
diff --git a/labs/azure-management/src/test/java/org/jclouds/azure/management/features/LocationApiLiveTest.java b/labs/azure-management/src/test/java/org/jclouds/azure/management/features/LocationApiLiveTest.java
new file mode 100644
index 0000000..fb3d810
--- /dev/null
+++ b/labs/azure-management/src/test/java/org/jclouds/azure/management/features/LocationApiLiveTest.java
@@ -0,0 +1,66 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.azure.management.features;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Preconditions.checkState;
+
+import java.util.Set;
+
+import org.jclouds.azure.management.domain.Location;
+import org.jclouds.azure.management.internal.BaseAzureManagementApiLiveTest;
+import org.testng.annotations.Test;
+
+import com.google.common.base.Predicate;
+import com.google.common.base.Predicates;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Iterables;
+
+/**
+ * @author Adrian Cole
+ */
+@Test(groups = "live", testName = "LocationApiLiveTest")
+public class LocationApiLiveTest extends BaseAzureManagementApiLiveTest {
+
+   @Test
+   protected void testList() {
+      Set<Location> response = api().list();
+
+      for (Location location : response) {
+         checkLocation(location);
+      }
+
+   }
+
+   protected Predicate<String> knownServices = Predicates.in(ImmutableSet.of("Compute", "Storage", "PersistentVMRole"));
+
+   private void checkLocation(Location location) {
+      checkNotNull(location.getName(), "Name cannot be null for a Location.");
+      checkNotNull(location.getDisplayName(), "DisplayName cannot be null for Location %s", location.getName());
+      checkNotNull(location.getAvailableServices(), "AvailableServices cannot be null for Location %s",
+               location.getName());
+      checkState(Iterables.all(location.getAvailableServices(), knownServices),
+               "AvailableServices in Location %s didn't match %s: %s", location.getName(), knownServices,
+               location.getAvailableServices());
+   }
+
+   protected LocationApi api() {
+      return context.getApi().getLocationApi();
+   }
+}
diff --git a/labs/azure-management/src/test/java/org/jclouds/azure/management/features/OSImageApiExpectTest.java b/labs/azure-management/src/test/java/org/jclouds/azure/management/features/OSImageApiExpectTest.java
new file mode 100644
index 0000000..7431b7e
--- /dev/null
+++ b/labs/azure-management/src/test/java/org/jclouds/azure/management/features/OSImageApiExpectTest.java
@@ -0,0 +1,120 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unles 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 expres or implied.  See the License for the
+ * specific language governing permisions and limitations
+ * under the License.
+ */
+package org.jclouds.azure.management.features;
+
+import static org.testng.Assert.assertEquals;
+
+import java.net.URI;
+
+import org.jclouds.azure.management.AzureManagementApi;
+import org.jclouds.azure.management.domain.OSImageParams;
+import org.jclouds.azure.management.domain.OSType;
+import org.jclouds.azure.management.internal.BaseAzureManagementApiExpectTest;
+import org.jclouds.azure.management.parse.ListOSImagesTest;
+import org.jclouds.http.HttpRequest;
+import org.jclouds.http.HttpResponse;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.ImmutableSet;
+
+/**
+ * @author Adrian Cole
+ */
+@Test(groups = "unit", testName = "OSImageApiExpectTest")
+public class OSImageApiExpectTest extends BaseAzureManagementApiExpectTest {
+
+   private static final String IMAGE_NAME = "myimage";
+   
+   HttpRequest list = HttpRequest.builder().method("GET")
+                                 .endpoint("https://management.core.windows.net/" + subscriptionId + "/services/images")
+                                 .addHeader("x-ms-version", "2012-03-01")
+                                 .addHeader("Accept", "application/xml").build();
+   
+   public void testListWhenResponseIs2xx() throws Exception {
+
+      HttpResponse listResponse = HttpResponse.builder().statusCode(200)
+            .payload(payloadFromResourceWithContentType("/images.xml", "application/xml")).build();
+
+      AzureManagementApi apiWhenExist = requestSendsResponse(
+            list, listResponse);
+
+      assertEquals(apiWhenExist.getOSImageApi().list().toString(), new ListOSImagesTest().expected().toString());
+   }
+
+   public void testListWhenResponseIs404() throws Exception {
+
+      HttpResponse listResponse = HttpResponse.builder().statusCode(404).build();
+
+      AzureManagementApi apiWhenDontExist = requestSendsResponse(
+            list, listResponse);
+
+      assertEquals(apiWhenDontExist.getOSImageApi().list(), ImmutableSet.of());
+   }
+
+   HttpRequest add = HttpRequest.builder().method("POST")
+            .endpoint("https://management.core.windows.net/" + subscriptionId + "/services/images")
+            .addHeader("x-ms-version", "2012-03-01")
+            .payload(payloadFromResourceWithContentType("/imageparams.xml", "application/xml")).build();
+   
+   public void testAddWhenResponseIs2xx() throws Exception {
+      HttpResponse addResponse = HttpResponse.builder().statusCode(200).build();
+
+      AzureManagementApi apiWhenExist = requestSendsResponse(add, addResponse);
+
+      OSImageParams params = OSImageParams.builder().name(IMAGE_NAME).label("foo").os(OSType.LINUX)
+               .mediaLink(URI.create("http://example.blob.core.windows.net/disks/mydisk.vhd")).build();
+      apiWhenExist.getOSImageApi().add(params);
+   }
+
+   HttpRequest update = HttpRequest.builder().method("PUT")
+            .endpoint("https://management.core.windows.net/" + subscriptionId + "/services/images/" + IMAGE_NAME)
+            .addHeader("x-ms-version", "2012-03-01")
+            .payload(payloadFromResourceWithContentType("/imageparams.xml", "application/xml")).build();
+   
+   public void testUpdateWhenResponseIs2xx() throws Exception {
+      HttpResponse updateResponse = HttpResponse.builder().statusCode(200).build();
+
+      AzureManagementApi apiWhenExist = requestSendsResponse(update, updateResponse);
+
+      OSImageParams params = OSImageParams.builder().name(IMAGE_NAME).label("foo").os(OSType.LINUX)
+               .mediaLink(URI.create("http://example.blob.core.windows.net/disks/mydisk.vhd")).build();
+      apiWhenExist.getOSImageApi().update(params);
+   }
+   
+   HttpRequest delete = HttpRequest.builder().method("DELETE")
+            .endpoint("https://management.core.windows.net/" + subscriptionId + "/services/images/" + IMAGE_NAME)
+            .addHeader("x-ms-version", "2012-03-01")
+            .build();
+   
+   public void testDeleteWhenResponseIs2xx() throws Exception {
+      HttpResponse deleteResponse = HttpResponse.builder().statusCode(200).build();
+
+      AzureManagementApi apiWhenExist = requestSendsResponse(delete, deleteResponse);
+
+      apiWhenExist.getOSImageApi().delete(IMAGE_NAME);
+   }
+
+   public void testDeleteWhenResponseIs404() throws Exception {
+      HttpResponse deleteResponse = HttpResponse.builder().statusCode(404).build();
+
+      AzureManagementApi apiWhenDontExist = requestSendsResponse(delete, deleteResponse);
+
+      apiWhenDontExist.getOSImageApi().delete(IMAGE_NAME);
+   }
+}
diff --git a/labs/azure-management/src/test/java/org/jclouds/azure/management/features/OSImageApiLiveTest.java b/labs/azure-management/src/test/java/org/jclouds/azure/management/features/OSImageApiLiveTest.java
new file mode 100644
index 0000000..a7d0bcd
--- /dev/null
+++ b/labs/azure-management/src/test/java/org/jclouds/azure/management/features/OSImageApiLiveTest.java
@@ -0,0 +1,121 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.azure.management.features;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.collect.Iterables.transform;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertNotEquals;
+import static org.testng.Assert.assertTrue;
+
+import java.util.Set;
+
+import org.jclouds.azure.management.domain.Location;
+import org.jclouds.azure.management.domain.OSImage;
+import org.jclouds.azure.management.domain.OSType;
+import org.jclouds.azure.management.internal.BaseAzureManagementApiLiveTest;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import com.google.common.base.Function;
+import com.google.common.collect.ImmutableSet;
+
+/**
+ * @author Adrian Cole
+ */
+@Test(groups = "live", testName = "OSImageApiLiveTest")
+public class OSImageApiLiveTest extends BaseAzureManagementApiLiveTest {
+
+   private ImmutableSet<String> locations;
+
+   @BeforeClass(groups = { "integration", "live" })
+   public void setupContext() {
+      super.initializeContext();
+
+      locations = ImmutableSet.copyOf(transform(context.getApi().getLocationApi().list(),
+               new Function<Location, String>() {
+                  @Override
+                  public String apply(Location in) {
+                     return in.getName();
+                  }
+               }));
+   }
+
+   @Test
+   protected void testList() {
+      Set<OSImage> response = api().list();
+
+      for (OSImage image : response) {
+         checkOSImage(image);
+      }
+   }
+
+   private void checkOSImage(OSImage image) {
+      checkNotNull(image.getLabel(), "Label cannot be null for OSImage %s", image);
+      checkNotNull(image.getName(), "Name cannot be null for OSImage %s", image.getLabel());
+      checkNotNull(image.getOS(), "OS cannot be null for OSImage: %s", image);
+      assertNotEquals(image.getOS(), OSType.UNRECOGNIZED, "Status cannot be UNRECOGNIZED for OSImage: " + image);
+
+      checkNotNull(image.getCategory(), "While Category can be null for OSImage, its Optional wrapper cannot: %s",
+               image);
+      if (image.getCategory().isPresent())
+         assertFalse(image.getCategory().get().trim().equals(""), "Invalid Category: " + image.toString());
+
+      checkNotNull(image.getLogicalSizeInGB(),
+               "While LogicalSizeInGB can be null for OSImage, its Optional wrapper cannot: %s", image);
+
+      if (image.getLogicalSizeInGB().isPresent())
+         assertTrue(image.getLogicalSizeInGB().get() > 0,
+                  "LogicalSizeInGB should be positive, if set" + image.toString());
+
+      checkNotNull(image.getMediaLink(), "While MediaLink can be null for OSImage, its Optional wrapper cannot: %s",
+               image);
+
+      if (image.getMediaLink().isPresent())
+         assertTrue(ImmutableSet.of("http", "https").contains(image.getMediaLink().get().getScheme()),
+                  "MediaLink should be an http(s) url" + image.toString());
+
+      checkNotNull(image.getDescription(),
+               "While Description can be null for OSImage, its Optional wrapper cannot: %s", image);
+
+      checkNotNull(image.getLocation(), "While Location can be null for OSImage, its Optional wrapper cannot: %s",
+               image);
+      if (image.getLocation().isPresent()) {
+         assertTrue(locations.contains(image.getLocation().get()),
+                  "Location not in " + locations + " :" + image.toString());
+      }
+      
+      checkNotNull(image.getEula(), "While Eula can be null for OSImage, its Optional wrapper cannot: %s",
+               image);
+      if (image.getEula().isPresent()) {
+         assertTrue(ImmutableSet.of("http", "https").contains(image.getEula().get().getScheme()),
+                  "Eula should be an http(s) url" + image.toString());
+      }
+
+      checkNotNull(image.getAffinityGroup(),
+               "While AffinityGroup can be null for OSImage, its Optional wrapper cannot: %s", image);
+      if (image.getAffinityGroup().isPresent()) {
+         // TODO: list getAffinityGroups and check if there
+      }
+   }
+
+   protected OSImageApi api() {
+      return context.getApi().getOSImageApi();
+   }
+}
diff --git a/labs/azure-management/src/test/java/org/jclouds/azure/management/features/OperationApiExpectTest.java b/labs/azure-management/src/test/java/org/jclouds/azure/management/features/OperationApiExpectTest.java
new file mode 100644
index 0000000..321c67f
--- /dev/null
+++ b/labs/azure-management/src/test/java/org/jclouds/azure/management/features/OperationApiExpectTest.java
@@ -0,0 +1,60 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unles 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 expres or implied.  See the License for the
+ * specific language governing permisions and limitations
+ * under the License.
+ */
+package org.jclouds.azure.management.features;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNull;
+
+import org.jclouds.azure.management.AzureManagementApi;
+import org.jclouds.azure.management.internal.BaseAzureManagementApiExpectTest;
+import org.jclouds.azure.management.parse.GetOperationTest;
+import org.jclouds.http.HttpRequest;
+import org.jclouds.http.HttpResponse;
+import org.testng.annotations.Test;
+
+/**
+ * @author Adrian Cole
+ */
+@Test(groups = "unit", testName = "OperationApiExpectTest")
+public class OperationApiExpectTest extends BaseAzureManagementApiExpectTest {
+   private final static String REQUEST_ID ="request-id";
+
+   HttpRequest get = HttpRequest.builder().method("GET")
+            .endpoint("https://management.core.windows.net/" + subscriptionId + "/operations/" + REQUEST_ID)
+            .addHeader("x-ms-version", "2012-03-01")
+            .addHeader("Accept", "application/xml").build();
+   
+   public void testGetWhenResponseIs2xx() throws Exception {
+      HttpResponse getResponse = HttpResponse.builder().statusCode(200)
+               .payload(payloadFromResourceWithContentType("/operation.xml", "application")).build();
+
+      AzureManagementApi apiWhenExist = requestSendsResponse(get, getResponse);
+
+      assertEquals(apiWhenExist.getOperationApi().get(REQUEST_ID).toString(), new GetOperationTest().expected().toString());
+   }
+
+   public void testGetWhenResponseIs404() throws Exception {
+      HttpResponse getResponse = HttpResponse.builder().statusCode(404).build();
+
+      AzureManagementApi apiWhenDontExist = requestSendsResponse(get, getResponse);
+
+      assertNull(apiWhenDontExist.getOperationApi().get(REQUEST_ID));
+   }
+
+}
diff --git a/labs/azure-management/src/test/java/org/jclouds/azure/management/features/RoleApiExpectTest.java b/labs/azure-management/src/test/java/org/jclouds/azure/management/features/RoleApiExpectTest.java
new file mode 100644
index 0000000..8626b88
--- /dev/null
+++ b/labs/azure-management/src/test/java/org/jclouds/azure/management/features/RoleApiExpectTest.java
@@ -0,0 +1,178 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unles 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 expres or implied.  See the License for the
+ * specific language governing permisions and limitations
+ * under the License.
+ */
+package org.jclouds.azure.management.features;
+
+import org.jclouds.azure.management.AzureManagementApi;
+import org.jclouds.azure.management.domain.DeploymentParams;
+import org.jclouds.azure.management.domain.OSType;
+import org.jclouds.azure.management.domain.RoleSize;
+import org.jclouds.azure.management.internal.BaseAzureManagementApiExpectTest;
+import org.jclouds.http.HttpRequest;
+import org.jclouds.http.HttpResponse;
+import org.testng.annotations.Test;
+
+/**
+ * @author Gérald Pereira
+ */
+@Test(groups = "unit", testName = "RoleApiExpectTest")
+public class RoleApiExpectTest extends BaseAzureManagementApiExpectTest {
+
+	private static final String DEPLOYMENT_NAME = "mydeployment";
+	private static final String IMAGE_NAME = "myImageName";
+	private static final String IMAGE_LABEL = "myImageLabel";
+
+	HttpRequest add = HttpRequest
+			.builder()
+			.method("POST")
+			.endpoint(
+					"https://management.core.windows.net/" + subscriptionId
+							+ "/services/hostedservices/" + DEPLOYMENT_NAME
+							+ "/deployments")
+			.addHeader("x-ms-version", "2012-03-01")
+			.addHeader("Accept", "application/atom+xml")
+			.payload(
+					payloadFromResourceWithContentType("/deploymentparams.xml",
+							"application/atom+xml")).build();
+
+	public void testAddWhenResponseIs2xx() throws Exception {
+		HttpResponse addResponse = HttpResponse.builder().statusCode(200)
+				.addHeader("x-ms-request-id", "fakerequestid").build();
+
+		AzureManagementApi apiWhenExist = requestSendsResponse(add, addResponse);
+		DeploymentParams params = DeploymentParams
+				.builder()
+				.osType(OSType.LINUX)
+				.name(DEPLOYMENT_NAME)
+				.username("username")
+				.password("testpwd")
+				.size(RoleSize.MEDIUM)
+				.sourceImageName(
+						"OpenLogic__OpenLogic-CentOS-62-20120531-en-us-30GB.vhd")
+				.storageAccount("portalvhds0g7xhnq2x7t21").build();
+
+		apiWhenExist.getRoleApi().createDeployment(DEPLOYMENT_NAME, params);
+	}
+
+	HttpRequest start = HttpRequest
+			.builder()
+			.method("POST")
+			.endpoint(
+					"https://management.core.windows.net/" + subscriptionId
+							+ "/services/hostedservices/" + DEPLOYMENT_NAME
+							+ "/deployments/" + DEPLOYMENT_NAME
+							+ "/roleInstances/" + DEPLOYMENT_NAME
+							+ "/Operations")
+			.addHeader("x-ms-version", "2012-03-01")
+			.addHeader("Accept", "application/atom+xml")
+			.payload(
+					payloadFromResourceWithContentType("/startrolepayload.xml",
+							"application/atom+xml")).build();
+
+	public void testStartWhenResponseIs2xx() throws Exception {
+		HttpResponse addResponse = HttpResponse.builder().statusCode(200)
+				.addHeader("x-ms-request-id", "fakerequestid").build();
+
+		AzureManagementApi apiWhenExist = requestSendsResponse(start,
+				addResponse);
+
+		apiWhenExist.getRoleApi().startRole(DEPLOYMENT_NAME, DEPLOYMENT_NAME,
+				DEPLOYMENT_NAME);
+	}
+
+	HttpRequest shutdown = HttpRequest
+			.builder()
+			.method("POST")
+			.endpoint(
+					"https://management.core.windows.net/" + subscriptionId
+							+ "/services/hostedservices/" + DEPLOYMENT_NAME
+							+ "/deployments/" + DEPLOYMENT_NAME
+							+ "/roleInstances/" + DEPLOYMENT_NAME
+							+ "/Operations")
+			.addHeader("x-ms-version", "2012-03-01")
+			.addHeader("Accept", "application/atom+xml")
+			.payload(
+					payloadFromResourceWithContentType(
+							"/shutdownrolepayload.xml", "application/atom+xml"))
+			.build();
+
+	public void testShutdownWhenResponseIs2xx() throws Exception {
+		HttpResponse addResponse = HttpResponse.builder().statusCode(200)
+				.addHeader("x-ms-request-id", "fakerequestid").build();
+
+		AzureManagementApi apiWhenExist = requestSendsResponse(shutdown,
+				addResponse);
+
+		apiWhenExist.getRoleApi().shutdownRole(DEPLOYMENT_NAME,
+				DEPLOYMENT_NAME, DEPLOYMENT_NAME);
+	}
+
+	HttpRequest restart = HttpRequest
+			.builder()
+			.method("POST")
+			.endpoint(
+					"https://management.core.windows.net/" + subscriptionId
+							+ "/services/hostedservices/" + DEPLOYMENT_NAME
+							+ "/deployments/" + DEPLOYMENT_NAME
+							+ "/roleInstances/" + DEPLOYMENT_NAME
+							+ "/Operations")
+			.addHeader("x-ms-version", "2012-03-01")
+			.addHeader("Accept", "application/atom+xml")
+			.payload(
+					payloadFromResourceWithContentType(
+							"/restartrolepayload.xml", "application/atom+xml"))
+			.build();
+
+	public void testRestartWhenResponseIs2xx() throws Exception {
+		HttpResponse addResponse = HttpResponse.builder().statusCode(200)
+				.addHeader("x-ms-request-id", "fakerequestid").build();
+
+		AzureManagementApi apiWhenExist = requestSendsResponse(restart,
+				addResponse);
+
+		apiWhenExist.getRoleApi().restartRole(DEPLOYMENT_NAME, DEPLOYMENT_NAME,
+				DEPLOYMENT_NAME);
+	}
+
+	HttpRequest capture = HttpRequest
+			.builder()
+			.method("POST")
+			.endpoint(
+					"https://management.core.windows.net/" + subscriptionId
+							+ "/services/hostedservices/" + DEPLOYMENT_NAME
+							+ "/deployments/" + DEPLOYMENT_NAME
+							+ "/roleInstances/" + DEPLOYMENT_NAME
+							+ "/Operations")
+			.addHeader("x-ms-version", "2012-03-01")
+			.addHeader("Accept", "application/atom+xml")
+			.payload(
+					payloadFromResourceWithContentType(
+							"/capturerolepayload.xml", "application/atom+xml"))
+			.build();
+
+	public void testCaptureWhenResponseIs2xx() throws Exception {
+		HttpResponse addResponse = HttpResponse.builder().statusCode(200)
+				.addHeader("x-ms-request-id", "fakerequestid").build();
+
+		AzureManagementApi apiWhenExist = requestSendsResponse(capture,
+				addResponse);
+
+		apiWhenExist.getRoleApi().captureRole(DEPLOYMENT_NAME, DEPLOYMENT_NAME,
+				DEPLOYMENT_NAME, IMAGE_NAME, IMAGE_LABEL);
+	}
+}
diff --git a/labs/azure-management/src/test/java/org/jclouds/azure/management/internal/BaseAzureManagementApiExpectTest.java b/labs/azure-management/src/test/java/org/jclouds/azure/management/internal/BaseAzureManagementApiExpectTest.java
new file mode 100644
index 0000000..b5522f4
--- /dev/null
+++ b/labs/azure-management/src/test/java/org/jclouds/azure/management/internal/BaseAzureManagementApiExpectTest.java
@@ -0,0 +1,29 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.azure.management.internal;
+
+import org.jclouds.azure.management.AzureManagementApi;
+
+/**
+ * 
+ * @author Adrian Cole
+ */
+public class BaseAzureManagementApiExpectTest extends BaseAzureManagementExpectTest<AzureManagementApi> {
+
+}
diff --git a/labs/azure-management/src/test/java/org/jclouds/azure/management/internal/BaseAzureManagementApiLiveTest.java b/labs/azure-management/src/test/java/org/jclouds/azure/management/internal/BaseAzureManagementApiLiveTest.java
new file mode 100644
index 0000000..649c28a
--- /dev/null
+++ b/labs/azure-management/src/test/java/org/jclouds/azure/management/internal/BaseAzureManagementApiLiveTest.java
@@ -0,0 +1,57 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.azure.management.internal;
+
+import java.util.Properties;
+
+import org.jclouds.apis.BaseContextLiveTest;
+import org.jclouds.azure.management.AzureManagementApi;
+import org.jclouds.azure.management.AzureManagementApiMetadata;
+import org.jclouds.azure.management.AzureManagementAsyncApi;
+import org.jclouds.azure.management.config.AzureManagementProperties;
+import org.jclouds.rest.RestContext;
+
+import com.google.common.reflect.TypeToken;
+
+/**
+ * 
+ * @author Adrian Cole
+ */
+public class BaseAzureManagementApiLiveTest extends
+         BaseContextLiveTest<RestContext<AzureManagementApi, AzureManagementAsyncApi>> {
+
+   protected String subscriptionId;
+
+   public BaseAzureManagementApiLiveTest() {
+      provider = "azure-management";
+   }
+   
+   @Override
+   protected Properties setupProperties() {
+      Properties props = super.setupProperties();
+      subscriptionId = setIfTestSystemPropertyPresent(props, AzureManagementProperties.SUBSCRIPTION_ID);
+      return props;
+   }
+
+   @Override
+   protected TypeToken<RestContext<AzureManagementApi, AzureManagementAsyncApi>> contextType() {
+      return AzureManagementApiMetadata.CONTEXT_TOKEN;
+   }
+
+}
diff --git a/labs/azure-management/src/test/java/org/jclouds/azure/management/internal/BaseAzureManagementAsyncApiExpectTest.java b/labs/azure-management/src/test/java/org/jclouds/azure/management/internal/BaseAzureManagementAsyncApiExpectTest.java
new file mode 100644
index 0000000..f939374
--- /dev/null
+++ b/labs/azure-management/src/test/java/org/jclouds/azure/management/internal/BaseAzureManagementAsyncApiExpectTest.java
@@ -0,0 +1,38 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.azure.management.internal;
+
+import java.util.Properties;
+
+import org.jclouds.azure.management.AzureManagementAsyncApi;
+import org.jclouds.http.HttpRequest;
+import org.jclouds.http.HttpResponse;
+
+import com.google.common.base.Function;
+import com.google.inject.Module;
+
+/**
+ * 
+ * @author Adrian Cole
+ */
+public class BaseAzureManagementAsyncApiExpectTest extends BaseAzureManagementExpectTest<AzureManagementAsyncApi> {
+   public AzureManagementAsyncApi createApi(Function<HttpRequest, HttpResponse> fn, Module module, Properties props) {
+      return createInjector(fn, module, props).getInstance(AzureManagementAsyncApi.class);
+   }
+}
diff --git a/labs/azure-management/src/test/java/org/jclouds/azure/management/internal/BaseAzureManagementExpectTest.java b/labs/azure-management/src/test/java/org/jclouds/azure/management/internal/BaseAzureManagementExpectTest.java
new file mode 100644
index 0000000..a6112cb
--- /dev/null
+++ b/labs/azure-management/src/test/java/org/jclouds/azure/management/internal/BaseAzureManagementExpectTest.java
@@ -0,0 +1,61 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.azure.management.internal;
+
+import java.util.Properties;
+
+import org.jclouds.azure.management.config.AzureManagementProperties;
+import org.jclouds.azure.management.config.AzureManagementRestClientModule;
+import org.jclouds.rest.ConfiguresRestClient;
+import org.jclouds.rest.internal.BaseRestApiExpectTest;
+
+import com.google.inject.Module;
+
+/**
+ * 
+ * @author Adrian Cole
+ */
+public class BaseAzureManagementExpectTest<T> extends BaseRestApiExpectTest<T> {
+   protected String subscriptionId = "a01234b5c-d6e7-8f9g-h0123-4567i890j1k";
+   
+   public BaseAzureManagementExpectTest() {
+      provider = "azure-management";
+      // self-signed dummy cert:
+      // keytool -genkey -alias test -keyalg RSA -keysize 1024 -validity 5475 -dname "CN=localhost" -keystore azure-test.p12 -storepass azurepass -storetype pkcs12
+      identity = this.getClass().getResource("/azure-test.p12").getFile();
+      credential = "azurepass";
+   }
+   
+   @Override
+   protected Properties setupProperties() {
+      Properties props = super.setupProperties();
+      props.put(AzureManagementProperties.SUBSCRIPTION_ID, subscriptionId);
+      return props;
+   }
+   
+   @ConfiguresRestClient
+   private static final class TestAzureManagementRestClientModule extends AzureManagementRestClientModule {
+
+   }
+
+   @Override
+   protected Module createModule() {
+      return new TestAzureManagementRestClientModule();
+   }
+}
diff --git a/labs/azure-management/src/test/java/org/jclouds/azure/management/parse/ErrorTest.java b/labs/azure-management/src/test/java/org/jclouds/azure/management/parse/ErrorTest.java
new file mode 100644
index 0000000..a36c1dc
--- /dev/null
+++ b/labs/azure-management/src/test/java/org/jclouds/azure/management/parse/ErrorTest.java
@@ -0,0 +1,57 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.azure.management.parse;
+
+import static org.testng.Assert.assertEquals;
+
+import java.io.InputStream;
+
+import org.jclouds.azure.management.domain.Error;
+import org.jclouds.azure.management.domain.Error.Code;
+import org.jclouds.azure.management.xml.ErrorHandler;
+import org.jclouds.http.functions.BaseHandlerTest;
+import org.testng.annotations.Test;
+
+/**
+ * @author Adrian Cole
+ */
+// NOTE:without testName, this will not call @Before* and fail w/NPE during surefire
+@Test(groups = "unit", testName = "ErrorTest")
+public class ErrorTest extends BaseHandlerTest {
+
+   public void test() {
+      InputStream is = getClass().getResourceAsStream("/error.xml");
+
+      Error expected = expected();
+
+      ErrorHandler handler = injector.getInstance(ErrorHandler.class);
+      Error result = factory.create(handler).parse(is);
+
+      assertEquals(result.toString(), expected.toString());
+
+   }
+
+   public Error expected() {
+      return Error.builder()
+                  .rawCode("MissingOrInvalidRequiredQueryParameter")
+                  .code(Code.MISSING_OR_INVALID_REQUIRED_QUERY_PARAMETER)
+                  .message("A required query parameter was not specified for this request or was specified incorrectly.")
+                  .build();
+   }
+}
diff --git a/labs/azure-management/src/test/java/org/jclouds/azure/management/parse/GetDeploymentTest.java b/labs/azure-management/src/test/java/org/jclouds/azure/management/parse/GetDeploymentTest.java
new file mode 100644
index 0000000..5380203
--- /dev/null
+++ b/labs/azure-management/src/test/java/org/jclouds/azure/management/parse/GetDeploymentTest.java
@@ -0,0 +1,70 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.azure.management.parse;
+
+import static org.testng.Assert.assertEquals;
+
+import java.io.InputStream;
+import java.net.URI;
+
+import org.jclouds.azure.management.domain.Deployment;
+import org.jclouds.azure.management.domain.DeploymentSlot;
+import org.jclouds.azure.management.domain.DeploymentStatus;
+import org.jclouds.azure.management.domain.InstanceStatus;
+import org.jclouds.azure.management.domain.RoleSize;
+import org.jclouds.azure.management.xml.DeploymentHandler;
+import org.jclouds.http.functions.BaseHandlerTest;
+import org.testng.annotations.Test;
+
+/**
+ * @author Gérald Pereira
+ */
+// NOTE:without testName, this will not call @Before* and fail w/NPE during surefire
+@Test(groups = "unit", testName = "GetDeploymentTest")
+public class GetDeploymentTest extends BaseHandlerTest {
+
+   public void test() {
+      InputStream is = getClass().getResourceAsStream("/deployment.xml");
+
+      Deployment expected = expected();
+
+      DeploymentHandler handler = injector.getInstance(DeploymentHandler.class);
+      Deployment result = factory.create(handler).parse(is);
+
+      assertEquals(result.toString(), expected.toString());
+
+   }
+
+   public Deployment expected() {
+      return Deployment.builder()
+    		  .deploymentName("neotysss")
+    		  .deploymentSlot(DeploymentSlot.PRODUCTION)
+    		  .deploymentStatus(DeploymentStatus.RUNNING)
+    		  .deploymentLabel("neotysss")
+    		  .deploymentURL(URI.create("http://neotysss.cloudapp.net/"))
+    		  .roleName("neotysss")
+    		  .instanceName("neotysss")
+    		  .instanceStatus(InstanceStatus.READY_ROLE)
+    		  .instanceSize(RoleSize.MEDIUM)
+    		  .privateIpAddress("10.59.244.162")
+    		  .publicIpAddress("168.63.27.148")
+    		  .build();
+   }
+
+}
diff --git a/labs/azure-management/src/test/java/org/jclouds/azure/management/parse/GetHostedServiceDetailsTest.java b/labs/azure-management/src/test/java/org/jclouds/azure/management/parse/GetHostedServiceDetailsTest.java
new file mode 100644
index 0000000..2a076da
--- /dev/null
+++ b/labs/azure-management/src/test/java/org/jclouds/azure/management/parse/GetHostedServiceDetailsTest.java
@@ -0,0 +1,72 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.azure.management.parse;
+
+import static org.testng.Assert.assertEquals;
+
+import java.io.InputStream;
+import java.net.URI;
+
+import org.jclouds.azure.management.domain.DetailedHostedServiceProperties;
+import org.jclouds.azure.management.domain.HostedService;
+import org.jclouds.azure.management.domain.HostedService.Status;
+import org.jclouds.azure.management.domain.HostedServiceWithDetailedProperties;
+import org.jclouds.azure.management.xml.HostedServiceWithDetailedPropertiesHandler;
+import org.jclouds.date.DateService;
+import org.jclouds.date.internal.SimpleDateFormatDateService;
+import org.jclouds.http.functions.BaseHandlerTest;
+import org.testng.annotations.Test;
+
+/**
+ * @author Adrian Cole
+ */
+// NOTE:without testName, this will not call @Before* and fail w/NPE during surefire
+@Test(groups = "unit", testName = "DetailedHostedServiceProperties")
+public class GetHostedServiceDetailsTest extends BaseHandlerTest {
+
+   public void test() {
+      InputStream is = getClass().getResourceAsStream("/hostedservice_details.xml");
+
+      HostedService expected = expected();
+
+      HostedServiceWithDetailedPropertiesHandler handler = injector.getInstance(HostedServiceWithDetailedPropertiesHandler.class);
+      HostedServiceWithDetailedProperties result = HostedServiceWithDetailedProperties.class.cast(factory.create(handler).parse(is));
+
+      assertEquals(result.toString(), expected.toString());
+
+   }
+
+   protected final DateService dateService = new SimpleDateFormatDateService();
+
+   public HostedServiceWithDetailedProperties expected() {
+      return HostedServiceWithDetailedProperties.builder()
+                          .url(URI.create("https://management.core.windows.net/eb0347c3-68d4-4550-9b39-5e7e0f92f7db/services/hostedservices/neotys"))
+                          .name("neotys")
+                          .properties(DetailedHostedServiceProperties.builder()
+                                                                     .description("Implicitly created hosted service2012-08-06 14:55")
+                                                                     .location("West Europe")
+                                                                     .label("neotys")
+                                                                     .rawStatus("Created")
+                                                                     .status(Status.CREATED)
+                                                                     .created(dateService.iso8601SecondsDateParse("2012-08-06T14:55:17Z"))
+                                                                     .lastModified(dateService.iso8601SecondsDateParse("2012-08-06T15:50:34Z"))
+                                                                     .build())
+                          .build();
+   }
+}
diff --git a/labs/azure-management/src/test/java/org/jclouds/azure/management/parse/GetHostedServiceTest.java b/labs/azure-management/src/test/java/org/jclouds/azure/management/parse/GetHostedServiceTest.java
new file mode 100644
index 0000000..9dc835a
--- /dev/null
+++ b/labs/azure-management/src/test/java/org/jclouds/azure/management/parse/GetHostedServiceTest.java
@@ -0,0 +1,62 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.azure.management.parse;
+
+import static org.testng.Assert.assertEquals;
+
+import java.io.InputStream;
+import java.net.URI;
+
+import org.jclouds.azure.management.domain.HostedService;
+import org.jclouds.azure.management.domain.HostedServiceProperties;
+import org.jclouds.azure.management.xml.HostedServiceHandler;
+import org.jclouds.http.functions.BaseHandlerTest;
+import org.testng.annotations.Test;
+
+/**
+ * @author Adrian Cole
+ */
+// NOTE:without testName, this will not call @Before* and fail w/NPE during surefire
+@Test(groups = "unit", testName = "GetHostedServiceTest")
+public class GetHostedServiceTest extends BaseHandlerTest {
+
+   public void test() {
+      InputStream is = getClass().getResourceAsStream("/hostedservice.xml");
+
+      HostedService expected = expected();
+
+      HostedServiceHandler handler = injector.getInstance(HostedServiceHandler.class);
+      HostedService result = factory.create(handler).parse(is);
+
+      assertEquals(result.toString(), expected.toString());
+
+   }
+
+   public HostedService expected() {
+      return HostedService.builder()
+                          .url(URI.create("https://management.core.windows.net/eb0347c3-68d4-4550-9b39-5e7e0f92f7db/services/hostedservices/neotys"))
+                          .name("neotys")
+                          .properties(HostedServiceProperties.builder()
+                                                             .description("Implicitly created hosted service2012-08-06 14:55")
+                                                             .location("West Europe")
+                                                             .label("neotys")
+                                                             .build())
+                          .build();
+   }
+}
diff --git a/labs/azure-management/src/test/java/org/jclouds/azure/management/parse/GetOperationTest.java b/labs/azure-management/src/test/java/org/jclouds/azure/management/parse/GetOperationTest.java
new file mode 100644
index 0000000..d0bcc76
--- /dev/null
+++ b/labs/azure-management/src/test/java/org/jclouds/azure/management/parse/GetOperationTest.java
@@ -0,0 +1,65 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.azure.management.parse;
+
+import static org.testng.Assert.assertEquals;
+
+import java.io.InputStream;
+
+import org.jclouds.azure.management.domain.Error;
+import org.jclouds.azure.management.domain.Error.Code;
+import org.jclouds.azure.management.domain.Operation;
+import org.jclouds.azure.management.domain.Operation.Status;
+import org.jclouds.azure.management.xml.OperationHandler;
+import org.jclouds.http.functions.BaseHandlerTest;
+import org.testng.annotations.Test;
+
+/**
+ * @author Adrian Cole
+ */
+// NOTE:without testName, this will not call @Before* and fail w/NPE during surefire
+@Test(groups = "unit", testName = "GetOperationTest")
+public class GetOperationTest extends BaseHandlerTest {
+
+   public void test() {
+      InputStream is = getClass().getResourceAsStream("/operation.xml");
+
+      Operation expected = expected();
+
+      OperationHandler handler = injector.getInstance(OperationHandler.class);
+      Operation result = factory.create(handler).parse(is);
+
+      assertEquals(result.toString(), expected.toString());
+
+   }
+
+   public Operation expected() {
+      return Operation.builder()
+                      .id("request-id")
+                      .rawStatus("Failed")
+                      .status(Status.FAILED)
+                      .httpStatusCode(400)
+                      .error(Error.builder()
+                                  .rawCode("MissingOrInvalidRequiredQueryParameter")
+                                  .code(Code.MISSING_OR_INVALID_REQUIRED_QUERY_PARAMETER)
+                                  .message("A required query parameter was not specified for this request or was specified incorrectly.")
+                                  .build())
+                      .build();
+   }
+}
diff --git a/labs/azure-management/src/test/java/org/jclouds/azure/management/parse/ListDisksTest.java b/labs/azure-management/src/test/java/org/jclouds/azure/management/parse/ListDisksTest.java
new file mode 100644
index 0000000..2a84311
--- /dev/null
+++ b/labs/azure-management/src/test/java/org/jclouds/azure/management/parse/ListDisksTest.java
@@ -0,0 +1,78 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.azure.management.parse;
+
+import static org.testng.Assert.assertEquals;
+
+import java.io.InputStream;
+import java.net.URI;
+import java.util.Set;
+
+import org.jclouds.azure.management.domain.Disk;
+import org.jclouds.azure.management.domain.Disk.Attachment;
+import org.jclouds.azure.management.domain.OSType;
+import org.jclouds.azure.management.xml.ListDisksHandler;
+import org.jclouds.http.functions.BaseHandlerTest;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.ImmutableSet;
+
+/**
+ * @author Gérald Pereira
+ */
+// NOTE:without testName, this will not call @Before* and fail w/NPE during surefire
+@Test(groups = "unit", testName = "ListDisksTest")
+public class ListDisksTest extends BaseHandlerTest {
+
+   public void test() {
+      InputStream is = getClass().getResourceAsStream("/disks.xml");
+
+      Set<Disk> expected = expected();
+
+      ListDisksHandler handler = injector.getInstance(ListDisksHandler.class);
+      Set<Disk> result = factory.create(handler).parse(is);
+
+      assertEquals(result.toString(), expected.toString());
+
+   }
+
+   public Set<Disk> expected() {
+	   
+      return ImmutableSet.<Disk>builder()
+                         .add(Disk.builder()
+                                     .os(OSType.LINUX)
+                                     .location("West Europe")
+                                     .logicalSizeInGB(30)
+                                     .mediaLink(URI.create("http://neotysbucket1.blob.core.windows.net/vhds/testimage2-testimage2-2012-08-17.vhd"))
+                                     .name("testimage2-testimage2-0-20120817095145")
+                                     .sourceImage("OpenLogic__OpenLogic-CentOS-62-20120531-en-us-30GB.vhd")
+                                     .build())
+                          .add(Disk.builder()
+                        		  	 .attachedTo(Attachment.builder().deployment("neotysss").hostedService("neotysss").role("neotysss").build())
+                                     .os(OSType.WINDOWS)
+                                     .location("West Europe")
+                                     .logicalSizeInGB(30)
+                                     .mediaLink(URI.create("http://portalvhds0g7xhnq2x7t21.blob.core.windows.net/disks/neotysss/MSFT__Win2K8R2SP1-120612-1520-121206-01-en-us-30GB.vhd"))
+                                     .name("neotysss-neotysss-0-20120824091357")
+                                     .sourceImage("MSFT__Win2K8R2SP1-120612-1520-121206-01-en-us-30GB.vhd")
+                                     .build())
+                        .build();
+   }
+
+}
diff --git a/labs/azure-management/src/test/java/org/jclouds/azure/management/parse/ListHostedServicesTest.java b/labs/azure-management/src/test/java/org/jclouds/azure/management/parse/ListHostedServicesTest.java
new file mode 100644
index 0000000..e827862
--- /dev/null
+++ b/labs/azure-management/src/test/java/org/jclouds/azure/management/parse/ListHostedServicesTest.java
@@ -0,0 +1,87 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.azure.management.parse;
+
+import static org.testng.Assert.assertEquals;
+
+import java.io.InputStream;
+import java.net.URI;
+import java.util.Set;
+
+import org.jclouds.azure.management.domain.DetailedHostedServiceProperties;
+import org.jclouds.azure.management.domain.HostedService.Status;
+import org.jclouds.azure.management.domain.HostedServiceWithDetailedProperties;
+import org.jclouds.azure.management.xml.ListHostedServicesHandler;
+import org.jclouds.date.DateService;
+import org.jclouds.date.internal.SimpleDateFormatDateService;
+import org.jclouds.http.functions.BaseHandlerTest;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.ImmutableSet;
+
+/**
+ * @author Adrian Cole
+ */
+// NOTE:without testName, this will not call @Before* and fail w/NPE during surefire
+@Test(groups = "unit", testName = "ListHostedServicesTest")
+public class ListHostedServicesTest extends BaseHandlerTest {
+
+   public void test() {
+      InputStream is = getClass().getResourceAsStream("/hostedservices.xml");
+
+      Set<HostedServiceWithDetailedProperties> expected = expected();
+
+      ListHostedServicesHandler handler = injector.getInstance(ListHostedServicesHandler.class);
+      Set<HostedServiceWithDetailedProperties> result = factory.create(handler).parse(is);
+
+      assertEquals(result.toString(), expected.toString());
+
+   }
+
+   protected final DateService dateService = new SimpleDateFormatDateService();
+
+   public Set<HostedServiceWithDetailedProperties> expected() {
+      return ImmutableSet.<HostedServiceWithDetailedProperties>builder()
+                         .add(HostedServiceWithDetailedProperties.builder()
+                                      .url(URI.create("https://management.core.windows.net/eb0347c3-68d4-4550-9b39-5e7e0f92f7db/services/hostedservices/neotys"))
+                                      .name("neotys")
+                                      .properties(DetailedHostedServiceProperties.builder()
+                                               .description("Implicitly created hosted service2012-08-06  14:55")
+                                               .location("West Europe")
+                                               .label("neotys")
+                                               .rawStatus("Created")
+                                               .status(Status.CREATED)
+                                               .created(dateService.iso8601SecondsDateParse("2012-08-06T14:55:17Z"))
+                                               .lastModified(dateService.iso8601SecondsDateParse("2012-08-06T15:50:34Z"))
+                                               .build())
+                                      .build())
+                         .add(HostedServiceWithDetailedProperties.builder()
+                                      .url(URI.create("https://management.core.windows.net/eb0347c3-68d4-4550-9b39-5e7e0f92f7db/services/hostedservices/neotys3"))
+                                      .name("neotys3")
+                                      .properties(DetailedHostedServiceProperties.builder()
+                                               .location("West Europe")
+                                               .label("neotys3")
+                                               .rawStatus("Created")
+                                               .status(Status.CREATED)
+                                               .created(dateService.iso8601SecondsDateParse("2012-08-07T09:00:02Z"))
+                                               .lastModified(dateService.iso8601SecondsDateParse("2012-08-07T09:00:02Z"))
+                                               .build())
+                                      .build()).build();
+   }
+}
diff --git a/labs/azure-management/src/test/java/org/jclouds/azure/management/parse/ListLocationsTest.java b/labs/azure-management/src/test/java/org/jclouds/azure/management/parse/ListLocationsTest.java
new file mode 100644
index 0000000..b8c04f5
--- /dev/null
+++ b/labs/azure-management/src/test/java/org/jclouds/azure/management/parse/ListLocationsTest.java
@@ -0,0 +1,87 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.azure.management.parse;
+
+import static org.testng.Assert.assertEquals;
+
+import java.io.InputStream;
+import java.util.Set;
+
+import org.jclouds.azure.management.domain.Location;
+import org.jclouds.azure.management.xml.ListLocationsHandler;
+import org.jclouds.http.functions.BaseHandlerTest;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.ImmutableSet;
+
+/**
+ * @author Adrian Cole
+ */
+// NOTE:without testName, this will not call @Before* and fail w/NPE during surefire
+@Test(groups = "unit", testName = "LocationsTest")
+public class ListLocationsTest extends BaseHandlerTest {
+
+   public void test() {
+      InputStream is = getClass().getResourceAsStream("/locations.xml");
+
+      Set<Location> expected = expected();
+
+      ListLocationsHandler handler = injector.getInstance(ListLocationsHandler.class);
+      Set<Location> result = factory.create(handler).parse(is);
+
+      assertEquals(result.toString(), expected.toString());
+
+   }
+
+   public Set<Location> expected() {
+      Set<String> availableServices = ImmutableSet.of("Compute", "Storage","PersistentVMRole");
+      return ImmutableSet.<Location>builder()
+                         .add(Location.builder()
+                                      .name("West US")
+                                      .displayName("West US")
+                                      .availableServices(availableServices)
+                                      .build())
+                         .add(Location.builder()
+                                      .name("East US")
+                                      .displayName("East US")
+                                      .availableServices(availableServices)
+                                      .build())
+                         .add(Location.builder()
+                                      .name("East Asia")
+                                      .displayName("East Asia")
+                                      .availableServices(availableServices)
+                                      .build())
+                         .add(Location.builder()
+                                      .name("Southeast Asia")
+                                      .displayName("Southeast Asia")
+                                      .availableServices(availableServices)
+                                      .build())
+                         .add(Location.builder()
+                                      .name("North Europe")
+                                      .displayName("North Europe")
+                                      .availableServices(availableServices)
+                                      .build())
+                         .add(Location.builder()
+                                      .name("West Europe")
+                                      .displayName("West Europe")
+                                      .availableServices(availableServices)
+                                      .build()).build();
+   }
+
+}
diff --git a/labs/azure-management/src/test/java/org/jclouds/azure/management/parse/ListOSImagesTest.java b/labs/azure-management/src/test/java/org/jclouds/azure/management/parse/ListOSImagesTest.java
new file mode 100644
index 0000000..7bc3aaf
--- /dev/null
+++ b/labs/azure-management/src/test/java/org/jclouds/azure/management/parse/ListOSImagesTest.java
@@ -0,0 +1,127 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.azure.management.parse;
+
+import static org.testng.Assert.assertEquals;
+
+import java.io.InputStream;
+import java.net.URI;
+import java.util.Set;
+
+import org.jclouds.azure.management.domain.OSImage;
+import org.jclouds.azure.management.domain.OSType;
+import org.jclouds.azure.management.xml.ListOSImagesHandler;
+import org.jclouds.http.functions.BaseHandlerTest;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.ImmutableSet;
+
+/**
+ * @author Adrian Cole
+ */
+// NOTE:without testName, this will not call @Before* and fail w/NPE during surefire
+@Test(groups = "unit", testName = "ListOSImagesTest")
+public class ListOSImagesTest extends BaseHandlerTest {
+
+   public void test() {
+      InputStream is = getClass().getResourceAsStream("/images.xml");
+
+      Set<OSImage> expected = expected();
+
+      ListOSImagesHandler handler = injector.getInstance(ListOSImagesHandler.class);
+      Set<OSImage> result = factory.create(handler).parse(is);
+
+      assertEquals(result.toString(), expected.toString());
+
+   }
+
+   public Set<OSImage> expected() {
+      return ImmutableSet.<OSImage>builder()
+                         .add(OSImage.builder()
+                                     .category("Canonical")
+                                     .label("Ubuntu Server 12.04 LTS")
+                                     .logicalSizeInGB(30)
+                                     .name("CANONICAL__Canonical-Ubuntu-12-04-amd64-server-20120528.1.3-en-us-30GB.vhd")
+                                     .os(OSType.LINUX)
+                                     .eula(URI.create("http://www.ubuntu.com/project/about-ubuntu/licensing"))
+                                     .description("Ubuntu Server 12.04 LTS amd64 20120528 Cloud Image")
+                                     .build())
+                         .add(OSImage.builder()
+                                     .category("Microsoft")
+                                     .label("Windows Server 2008 R2 SP1, June 2012")
+                                     .logicalSizeInGB(30)
+                                     .name("MSFT__Win2K8R2SP1-120612-1520-121206-01-en-us-30GB.vhd")
+                                     .os(OSType.WINDOWS)
+                                     .description("Windows Server 2008 R2 is a multi-purpose server.")
+                                     .build())
+                         .add(OSImage.builder()
+                                     .category("Microsoft")
+                                     .label("Microsoft SQL Server 2012 Evaluation Edition")
+                                     .logicalSizeInGB(30)
+                                     .name("MSFT__Sql-Server-11EVAL-11.0.2215.0-05152012-en-us-30GB.vhd")
+                                     .os(OSType.WINDOWS)
+                                     .eula(URI.create("http://go.microsoft.com/fwlink/?LinkID=251820;http://go.microsoft.com/fwlink/?LinkID=131004"))
+                                     .description("SQL Server 2012 Evaluation Edition (64-bit).")
+                                     .build())
+                         .add(OSImage.builder()
+                                     .category("Microsoft")
+                                     .label("Windows Server 2012 Release Candidate, July 2012")
+                                     .logicalSizeInGB(30)
+                                     .name("MSFT__Win2K12RC-Datacenter-201207.02-en.us-30GB.vhd")
+                                     .os(OSType.WINDOWS)
+                                     .description("Windows Server 2012 incorporates Microsoft's experience building.")
+                                     .build())
+                         .add(OSImage.builder()
+                                     .category("Microsoft")
+                                     .label("Windows Server 2008 R2 SP1, July 2012")
+                                     .logicalSizeInGB(30)
+                                     .name("MSFT__Win2K8R2SP1-Datacenter-201207.01-en.us-30GB.vhd")
+                                     .os(OSType.WINDOWS)
+                                     .description("Windows Server 2008 R2 is a multi-purpose server.")
+                                     .build())
+                         .add(OSImage.builder()
+                                     .category("OpenLogic")
+                                     .label("OpenLogic CentOS 6.2")
+                                     .logicalSizeInGB(30)
+                                     .name("OpenLogic__OpenLogic-CentOS-62-20120531-en-us-30GB.vhd")
+                                     .os(OSType.LINUX)
+                                     .eula(URI.create("http://www.openlogic.com/azure/service-agreement/"))
+                                     .description("This distribution of Linux is based on CentOS.")
+                                     .build())
+                         .add(OSImage.builder()
+                                     .category("SUSE")
+                                     .label("openSUSE 12.1")
+                                     .logicalSizeInGB(30)
+                                     .name("SUSE__openSUSE-12-1-20120603-en-us-30GB.vhd")
+                                     .os(OSType.LINUX)
+                                     .eula(URI.create("http://opensuse.org/"))
+                                     .description("openSUSE is a free and Linux-based operating system!")
+                                     .build())
+                         .add(OSImage.builder()
+                                     .category("SUSE")
+                                     .label("SUSE Linux Enterprise Server")
+                                     .logicalSizeInGB(30)
+                                     .name("SUSE__SUSE-Linux-Enterprise-Server-11SP2-20120601-en-us-30GB.vhd")
+                                     .os(OSType.LINUX)
+                                     .eula(URI.create("http://www.novell.com/licensing/eula/"))
+                                     .description("SUSE Linux Enterprise Server is a highly reliable value.")
+                                     .build()).build();
+   }
+
+}
diff --git a/labs/azure-management/src/test/resources/azure-test.p12 b/labs/azure-management/src/test/resources/azure-test.p12
new file mode 100644
index 0000000..5250dd6
--- /dev/null
+++ b/labs/azure-management/src/test/resources/azure-test.p12
Binary files differ
diff --git a/labs/azure-management/src/test/resources/capturerolepayload.xml b/labs/azure-management/src/test/resources/capturerolepayload.xml
new file mode 100644
index 0000000..9414c52
--- /dev/null
+++ b/labs/azure-management/src/test/resources/capturerolepayload.xml
@@ -0,0 +1 @@
+<CaptureRoleOperation xmlns="http://schemas.microsoft.com/windowsazure" xmlns:i="http://www.w3.org/2001/XMLSchema-instance"><OperationType>CaptureRoleOperation</OperationType><PostCaptureAction>Delete</PostCaptureAction><TargetImageLabel>myImageLabel</TargetImageLabel><TargetImageName>myImageName</TargetImageName></CaptureRoleOperation>
\ No newline at end of file
diff --git a/labs/azure-management/src/test/resources/create_hostedservice_location.xml b/labs/azure-management/src/test/resources/create_hostedservice_location.xml
new file mode 100644
index 0000000..076f562
--- /dev/null
+++ b/labs/azure-management/src/test/resources/create_hostedservice_location.xml
@@ -0,0 +1 @@
+<CreateHostedService xmlns="http://schemas.microsoft.com/windowsazure"><ServiceName>myservice</ServiceName><Label>c2VydmljZSBtaW5l</Label><Location>West US</Location></CreateHostedService>
\ No newline at end of file
diff --git a/labs/azure-management/src/test/resources/create_hostedservice_location_options.xml b/labs/azure-management/src/test/resources/create_hostedservice_location_options.xml
new file mode 100644
index 0000000..9f7f8f0
--- /dev/null
+++ b/labs/azure-management/src/test/resources/create_hostedservice_location_options.xml
@@ -0,0 +1 @@
+<CreateHostedService xmlns="http://schemas.microsoft.com/windowsazure"><ServiceName>myservice</ServiceName><Label>c2VydmljZSBtaW5l</Label><Description>my description</Description><Location>West US</Location><ExtendedProperties><ExtendedProperty><Name>Role</Name><Value>Production</Value></ExtendedProperty></ExtendedProperties></CreateHostedService>
\ No newline at end of file
diff --git a/labs/azure-management/src/test/resources/deployment.xml b/labs/azure-management/src/test/resources/deployment.xml
new file mode 100644
index 0000000..94cebc9
--- /dev/null
+++ b/labs/azure-management/src/test/resources/deployment.xml
@@ -0,0 +1,70 @@
+<Deployment xmlns="http://schemas.microsoft.com/windowsazure" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
+    <Name>neotysss</Name>
+    <DeploymentSlot>Production</DeploymentSlot>
+    <PrivateID>05aa8ec5d8ee4215894431c7db401b31</PrivateID>
+    <Status>Running</Status>
+    <Label>bmVvdHlzc3M=</Label>
+    <Url>http://neotysss.cloudapp.net/</Url>
+    <Configuration>PFNlcnZpY2VDb25maWd1cmF0aW9uIHhtbG5zOnhzaT0iaHR0cDovL3d3dy53My5vcmcvMjAwMS9YTUxTY2hlbWEtaW5zdGFuY2UiIHhtbG5zOnhzZD0iaHR0cDovL3d3dy53My5vcmcvMjAwMS9YTUxTY2hlbWEiIHhtbG5zPSJodHRwOi8vc2NoZW1hcy5taWNyb3NvZnQuY29tL1NlcnZpY2VIb3N0aW5nLzIwMDgvMTAvU2VydmljZUNvbmZpZ3VyYXRpb24iPg0KICA8Um9sZSBuYW1lPSJuZW90eXNzcyI+DQogICAgPEluc3RhbmNlcyBjb3VudD0iMSIgLz4NCiAgPC9Sb2xlPg0KPC9TZXJ2aWNlQ29uZmlndXJhdGlvbj4=</Configuration>
+    <RoleInstanceList>
+        <RoleInstance>
+	        <RoleName>neotysss</RoleName>
+	        <InstanceName>neotysss</InstanceName>
+	        <InstanceStatus>ReadyRole</InstanceStatus>
+	        <InstanceUpgradeDomain>0</InstanceUpgradeDomain>
+	        <InstanceFaultDomain>0</InstanceFaultDomain>
+	        <InstanceSize>Medium</InstanceSize>
+	        <InstanceStateDetails/>
+	        <IpAddress>10.59.244.162</IpAddress>
+	        <InstanceEndpoints>
+	            <InstanceEndpoint>
+		        <Name>SSH</Name>
+		        <Vip>168.63.27.148</Vip>
+		        <PublicPort>22</PublicPort>
+		        <LocalPort>22</LocalPort>
+		        <Protocol>tcp</Protocol>
+			    </InstanceEndpoint>
+		    </InstanceEndpoints>
+	        <PowerState>Started</PowerState>
+	        <HostName>neotys</HostName>
+	    </RoleInstance>
+    </RoleInstanceList>
+    <UpgradeDomainCount>1</UpgradeDomainCount>
+    <RoleList>
+        <Role i:type="PersistentVMRole">
+	        <RoleName>neotysss</RoleName>
+	        <OsVersion/>
+	        <RoleType>PersistentVMRole</RoleType>
+	        <ConfigurationSets>
+		        <ConfigurationSet i:type="NetworkConfigurationSet">
+	    		    <ConfigurationSetType>NetworkConfiguration</ConfigurationSetType>
+	        		<InputEndpoints>
+	        			<InputEndpoint>
+		        			<LocalPort>22</LocalPort>
+		    				<Name>SSH</Name>
+		    				<Port>22</Port>
+		        			<Protocol>tcp</Protocol>
+		        			<Vip>168.63.27.148</Vip>
+				    	</InputEndpoint>
+	    			</InputEndpoints>
+	        		<SubnetNames/>
+	        	</ConfigurationSet>
+		    </ConfigurationSets>
+	        <DataVirtualHardDisks/>
+	        <OSVirtualHardDisk>
+		        <HostCaching>ReadWrite</HostCaching>
+		        <DiskName>neotysss-neotysss-0-20120824091357</DiskName>
+		        <MediaLink>http://portalvhds0g7xhnq2x7t21.blob.core.windows.net/disks/neotysss/MSFT__Win2K8R2SP1-120612-1520-121206-01-en-us-30GB.vhd</MediaLink>
+		        <SourceImageName>MSFT__Win2K8R2SP1-120612-1520-121206-01-en-us-30GB.vhd</SourceImageName>
+		        <OS>Windows</OS>
+		    </OSVirtualHardDisk>
+	        <RoleSize>Medium</RoleSize>
+	    </Role>
+    </RoleList>
+    <SdkVersion/>
+    <Locked>false</Locked>
+    <RollbackAllowed>false</RollbackAllowed>
+    <CreatedTime>2012-08-24T09:13:53Z</CreatedTime>
+    <LastModifiedTime>2012-08-27T08:55:13Z</LastModifiedTime>
+    <ExtendedProperties/>
+</Deployment>
\ No newline at end of file
diff --git a/labs/azure-management/src/test/resources/deploymentparams.xml b/labs/azure-management/src/test/resources/deploymentparams.xml
new file mode 100644
index 0000000..fadaff1
--- /dev/null
+++ b/labs/azure-management/src/test/resources/deploymentparams.xml
@@ -0,0 +1 @@
+<Deployment xmlns="http://schemas.microsoft.com/windowsazure"><Name>mydeployment</Name><DeploymentSlot>Production</DeploymentSlot><Label>mydeployment</Label><RoleList><Role><RoleName>mydeployment</RoleName><RoleType>PersistentVMRole</RoleType><ConfigurationSets><ConfigurationSet><ConfigurationSetType>LinuxProvisioningConfiguration</ConfigurationSetType><HostName>mydeployment</HostName><UserName>username</UserName><UserPassword>testpwd</UserPassword><DisableSshPasswordAuthentication>false</DisableSshPasswordAuthentication><SSH/></ConfigurationSet><ConfigurationSet><ConfigurationSetType>NetworkConfiguration</ConfigurationSetType><InputEndpoints/><SubnetNames/></ConfigurationSet></ConfigurationSets><DataVirtualHardDisks/><OSVirtualHardDisk><HostCaching>ReadWrite</HostCaching><MediaLink>http://portalvhds0g7xhnq2x7t21.blob.core.windows.net/disks/mydeployment/OpenLogic__OpenLogic-CentOS-62-20120531-en-us-30GB.vhd</MediaLink><SourceImageName>OpenLogic__OpenLogic-CentOS-62-20120531-en-us-30GB.vhd</SourceImageName><OS>Linux</OS></OSVirtualHardDisk><RoleSize>Medium</RoleSize></Role></RoleList></Deployment>
\ No newline at end of file
diff --git a/labs/azure-management/src/test/resources/disks.xml b/labs/azure-management/src/test/resources/disks.xml
new file mode 100644
index 0000000..9290a9a
--- /dev/null
+++ b/labs/azure-management/src/test/resources/disks.xml
@@ -0,0 +1,23 @@
+<Disks xmlns="http://schemas.microsoft.com/windowsazure" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
+    <Disk>
+        <OS>Linux</OS>
+        <Location>West Europe</Location>
+        <LogicalDiskSizeInGB>30</LogicalDiskSizeInGB>
+        <MediaLink>http://neotysbucket1.blob.core.windows.net/vhds/testimage2-testimage2-2012-08-17.vhd</MediaLink>
+        <Name>testimage2-testimage2-0-20120817095145</Name>
+        <SourceImageName>OpenLogic__OpenLogic-CentOS-62-20120531-en-us-30GB.vhd</SourceImageName>
+    </Disk>
+    <Disk>
+        <AttachedTo>
+            <DeploymentName>neotysss</DeploymentName>
+            <HostedServiceName>neotysss</HostedServiceName>
+            <RoleName>neotysss</RoleName>
+        </AttachedTo>
+        <OS>Windows</OS>
+        <Location>West Europe</Location>
+        <LogicalDiskSizeInGB>30</LogicalDiskSizeInGB>
+        <MediaLink>http://portalvhds0g7xhnq2x7t21.blob.core.windows.net/disks/neotysss/MSFT__Win2K8R2SP1-120612-1520-121206-01-en-us-30GB.vhd</MediaLink>
+        <Name>neotysss-neotysss-0-20120824091357</Name>
+        <SourceImageName>MSFT__Win2K8R2SP1-120612-1520-121206-01-en-us-30GB.vhd</SourceImageName>
+    </Disk>
+</Disks>
diff --git a/labs/azure-management/src/test/resources/error.xml b/labs/azure-management/src/test/resources/error.xml
new file mode 100644
index 0000000..a9f9b2f
--- /dev/null
+++ b/labs/azure-management/src/test/resources/error.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Error>
+  <Code>MissingOrInvalidRequiredQueryParameter</Code>
+  <Message>A required query parameter was not specified for this request or was specified incorrectly.</Message>
+</Error>
\ No newline at end of file
diff --git a/labs/azure-management/src/test/resources/hostedservice.xml b/labs/azure-management/src/test/resources/hostedservice.xml
new file mode 100644
index 0000000..625aeb3
--- /dev/null
+++ b/labs/azure-management/src/test/resources/hostedservice.xml
@@ -0,0 +1,10 @@
+<HostedService xmlns="http://schemas.microsoft.com/windowsazure">
+    <Url>https://management.core.windows.net/eb0347c3-68d4-4550-9b39-5e7e0f92f7db/services/hostedservices/neotys</Url>
+    <ServiceName>neotys</ServiceName>
+    <HostedServiceProperties>
+        <Description>Implicitly created hosted service2012-08-06 14:55
+        </Description>
+        <Location>West Europe</Location>
+        <Label>bmVvdHlz</Label>
+    </HostedServiceProperties>
+</HostedService>
\ No newline at end of file
diff --git a/labs/azure-management/src/test/resources/hostedservice_details.xml b/labs/azure-management/src/test/resources/hostedservice_details.xml
new file mode 100644
index 0000000..d730cc7
--- /dev/null
+++ b/labs/azure-management/src/test/resources/hostedservice_details.xml
@@ -0,0 +1,13 @@
+<HostedService xmlns="http://schemas.microsoft.com/windowsazure">
+    <Url>https://management.core.windows.net/eb0347c3-68d4-4550-9b39-5e7e0f92f7db/services/hostedservices/neotys</Url>
+    <ServiceName>neotys</ServiceName>
+    <HostedServiceProperties>
+        <Description>Implicitly created hosted service2012-08-06 14:55</Description>
+        <Location>West Europe</Location>
+        <Label>bmVvdHlz</Label>
+        <Status>Created</Status>
+        <DateCreated>2012-08-06T14:55:17Z</DateCreated>
+        <DateLastModified>2012-08-06T15:50:34Z</DateLastModified>
+        <ExtendedProperties />
+    </HostedServiceProperties>
+</HostedService>
\ No newline at end of file
diff --git a/labs/azure-management/src/test/resources/hostedservices.xml b/labs/azure-management/src/test/resources/hostedservices.xml
new file mode 100644
index 0000000..66b7589
--- /dev/null
+++ b/labs/azure-management/src/test/resources/hostedservices.xml
@@ -0,0 +1,29 @@
+<HostedServices xmlns="http://schemas.microsoft.com/windowsazure"
+    xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
+    <HostedService>
+        <Url>https://management.core.windows.net/eb0347c3-68d4-4550-9b39-5e7e0f92f7db/services/hostedservices/neotys</Url>
+        <ServiceName>neotys</ServiceName>
+        <HostedServiceProperties>
+            <Description>Implicitly created hosted service2012-08-06  14:55</Description>
+            <Location>West Europe</Location>
+            <Label>bmVvdHlz</Label>
+            <Status>Created</Status>
+            <DateCreated>2012-08-06T14:55:17Z</DateCreated>
+            <DateLastModified>2012-08-06T15:50:34Z</DateLastModified>
+            <ExtendedProperties />
+        </HostedServiceProperties>
+    </HostedService>
+    <HostedService>
+        <Url>https://management.core.windows.net/eb0347c3-68d4-4550-9b39-5e7e0f92f7db/services/hostedservices/neotys3</Url>
+        <ServiceName>neotys3</ServiceName>
+        <HostedServiceProperties>
+            <Description i:nil="true" />
+            <Location>West Europe</Location>
+            <Label>bmVvdHlzMw==</Label>
+            <Status>Created</Status>
+            <DateCreated>2012-08-07T09:00:02Z</DateCreated>
+            <DateLastModified>2012-08-07T09:00:02Z</DateLastModified>
+            <ExtendedProperties />
+        </HostedServiceProperties>
+    </HostedService>
+</HostedServices>
\ No newline at end of file
diff --git a/labs/azure-management/src/test/resources/imageparams.xml b/labs/azure-management/src/test/resources/imageparams.xml
new file mode 100644
index 0000000..d3279ba
--- /dev/null
+++ b/labs/azure-management/src/test/resources/imageparams.xml
@@ -0,0 +1 @@
+<OSImage xmlns="http://schemas.microsoft.com/windowsazure"><Label>foo</Label><MediaLink>http://example.blob.core.windows.net/disks/mydisk.vhd</MediaLink><Name>myimage</Name><OS>Linux</OS></OSImage>
\ No newline at end of file
diff --git a/labs/azure-management/src/test/resources/images.xml b/labs/azure-management/src/test/resources/images.xml
new file mode 100644
index 0000000..aa6efca
--- /dev/null
+++ b/labs/azure-management/src/test/resources/images.xml
@@ -0,0 +1,75 @@
+<Images xmlns="http://schemas.microsoft.com/windowsazure"
+    xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
+    <OSImage>
+        <Category>Canonical</Category>
+        <Label>Ubuntu Server 12.04 LTS</Label>
+        <LogicalSizeInGB>30</LogicalSizeInGB>
+        <Name>CANONICAL__Canonical-Ubuntu-12-04-amd64-server-20120528.1.3-en-us-30GB.vhd</Name>
+        <OS>Linux</OS>
+        <Eula>http://www.ubuntu.com/project/about-ubuntu/licensing</Eula>
+        <Description>Ubuntu Server 12.04 LTS amd64 20120528 Cloud Image</Description>
+    </OSImage>
+    <OSImage>
+        <Category>Microsoft</Category>
+        <Label>Windows Server 2008 R2 SP1, June 2012</Label>
+        <LogicalSizeInGB>30</LogicalSizeInGB>
+        <Name>MSFT__Win2K8R2SP1-120612-1520-121206-01-en-us-30GB.vhd</Name>
+        <OS>Windows</OS>
+        <Eula />
+        <Description>Windows Server 2008 R2 is a multi-purpose server.</Description>
+    </OSImage>
+    <OSImage>
+        <Category>Microsoft</Category>
+        <Label>Microsoft SQL Server 2012 Evaluation Edition</Label>
+        <LogicalSizeInGB>30</LogicalSizeInGB>
+        <Name>MSFT__Sql-Server-11EVAL-11.0.2215.0-05152012-en-us-30GB.vhd</Name>
+        <OS>Windows</OS>
+        <Eula>http://go.microsoft.com/fwlink/?LinkID=251820;http://go.microsoft.com/fwlink/?LinkID=131004</Eula>
+        <Description>SQL Server 2012 Evaluation Edition (64-bit).</Description>
+    </OSImage>
+    <OSImage>
+        <Category>Microsoft</Category>
+        <Label>Windows Server 2012 Release Candidate, July 2012</Label>
+        <LogicalSizeInGB>30</LogicalSizeInGB>
+        <Name>MSFT__Win2K12RC-Datacenter-201207.02-en.us-30GB.vhd</Name>
+        <OS>Windows</OS>
+        <Eula />
+        <Description>Windows Server 2012 incorporates Microsoft's experience building.</Description>
+    </OSImage>
+    <OSImage>
+        <Category>Microsoft</Category>
+        <Label>Windows Server 2008 R2 SP1, July 2012</Label>
+        <LogicalSizeInGB>30</LogicalSizeInGB>
+        <Name>MSFT__Win2K8R2SP1-Datacenter-201207.01-en.us-30GB.vhd</Name>
+        <OS>Windows</OS>
+        <Eula />
+        <Description>Windows Server 2008 R2 is a multi-purpose server.</Description>
+    </OSImage>
+    <OSImage>
+        <Category>OpenLogic</Category>
+        <Label>OpenLogic CentOS 6.2</Label>
+        <LogicalSizeInGB>30</LogicalSizeInGB>
+        <Name>OpenLogic__OpenLogic-CentOS-62-20120531-en-us-30GB.vhd</Name>
+        <OS>Linux</OS>
+        <Eula>http://www.openlogic.com/azure/service-agreement/</Eula>
+        <Description>This distribution of Linux is based on CentOS.</Description>
+    </OSImage>
+    <OSImage>
+        <Category>SUSE</Category>
+        <Label>openSUSE 12.1</Label>
+        <LogicalSizeInGB>30</LogicalSizeInGB>
+        <Name>SUSE__openSUSE-12-1-20120603-en-us-30GB.vhd</Name>
+        <OS>Linux</OS>
+        <Eula>http://opensuse.org/</Eula>
+        <Description>openSUSE is a free and Linux-based operating system!</Description>
+    </OSImage>
+    <OSImage>
+        <Category>SUSE</Category>
+        <Label>SUSE Linux Enterprise Server</Label>
+        <LogicalSizeInGB>30</LogicalSizeInGB>
+        <Name>SUSE__SUSE-Linux-Enterprise-Server-11SP2-20120601-en-us-30GB.vhd</Name>
+        <OS>Linux</OS>
+        <Eula>http://www.novell.com/licensing/eula/</Eula>
+        <Description>SUSE Linux Enterprise Server is a highly reliable value.</Description>
+    </OSImage>
+</Images>
\ No newline at end of file
diff --git a/labs/azure-management/src/test/resources/locations.xml b/labs/azure-management/src/test/resources/locations.xml
new file mode 100644
index 0000000..1c7dcc8
--- /dev/null
+++ b/labs/azure-management/src/test/resources/locations.xml
@@ -0,0 +1,57 @@
+<?xml version="1.0"?>
+<Locations xmlns="http://schemas.microsoft.com/windowsazure" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
+  <Location>
+    <Name>West US</Name>
+    <DisplayName>West US</DisplayName>
+    <AvailableServices>
+      <AvailableService>Compute</AvailableService>
+      <AvailableService>Storage</AvailableService>
+      <AvailableService>PersistentVMRole</AvailableService>
+    </AvailableServices>
+  </Location>
+  <Location>
+    <Name>East US</Name>
+    <DisplayName>East US</DisplayName>
+    <AvailableServices>
+      <AvailableService>Compute</AvailableService>
+      <AvailableService>Storage</AvailableService>
+      <AvailableService>PersistentVMRole</AvailableService>
+    </AvailableServices>
+  </Location>
+  <Location>
+    <Name>East Asia</Name>
+    <DisplayName>East Asia</DisplayName>
+    <AvailableServices>
+      <AvailableService>Compute</AvailableService>
+      <AvailableService>Storage</AvailableService>
+      <AvailableService>PersistentVMRole</AvailableService>
+    </AvailableServices>
+  </Location>
+  <Location>
+    <Name>Southeast Asia</Name>
+    <DisplayName>Southeast Asia</DisplayName>
+    <AvailableServices>
+      <AvailableService>Compute</AvailableService>
+      <AvailableService>Storage</AvailableService>
+      <AvailableService>PersistentVMRole</AvailableService>
+    </AvailableServices>
+  </Location>
+  <Location>
+    <Name>North Europe</Name>
+    <DisplayName>North Europe</DisplayName>
+    <AvailableServices>
+      <AvailableService>Compute</AvailableService>
+      <AvailableService>Storage</AvailableService>
+      <AvailableService>PersistentVMRole</AvailableService>
+    </AvailableServices>
+  </Location>
+  <Location>
+    <Name>West Europe</Name>
+    <DisplayName>West Europe</DisplayName>
+    <AvailableServices>
+      <AvailableService>Compute</AvailableService>
+      <AvailableService>Storage</AvailableService>
+      <AvailableService>PersistentVMRole</AvailableService>
+    </AvailableServices>
+  </Location>
+</Locations>
\ No newline at end of file
diff --git a/labs/azure-management/src/test/resources/operation.xml b/labs/azure-management/src/test/resources/operation.xml
new file mode 100644
index 0000000..498d1f0
--- /dev/null
+++ b/labs/azure-management/src/test/resources/operation.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Operation xmlns="http://schemas.microsoft.com/windowsazure">
+    <ID>request-id</ID>
+    <Status>Failed</Status>
+    <HttpStatusCode>400</HttpStatusCode>
+    <Error>
+        <Code>MissingOrInvalidRequiredQueryParameter</Code>
+        <Message>A required query parameter was not specified for this request or was specified incorrectly.</Message>
+    </Error>
+</Operation>
diff --git a/labs/azure-management/src/test/resources/restartrolepayload.xml b/labs/azure-management/src/test/resources/restartrolepayload.xml
new file mode 100644
index 0000000..4eca508
--- /dev/null
+++ b/labs/azure-management/src/test/resources/restartrolepayload.xml
@@ -0,0 +1 @@
+<RestartRoleOperation xmlns="http://schemas.microsoft.com/windowsazure" xmlns:i="http://www.w3.org/2001/XMLSchema-instance"><OperationType>RestartRoleOperation</OperationType></RestartRoleOperation>
\ No newline at end of file
diff --git a/labs/azure-management/src/test/resources/shutdownrolepayload.xml b/labs/azure-management/src/test/resources/shutdownrolepayload.xml
new file mode 100644
index 0000000..27beee8
--- /dev/null
+++ b/labs/azure-management/src/test/resources/shutdownrolepayload.xml
@@ -0,0 +1 @@
+<ShutdownRoleOperation xmlns="http://schemas.microsoft.com/windowsazure" xmlns:i="http://www.w3.org/2001/XMLSchema-instance"><OperationType>ShutdownRoleOperation</OperationType></ShutdownRoleOperation>
\ No newline at end of file
diff --git a/labs/azure-management/src/test/resources/startrolepayload.xml b/labs/azure-management/src/test/resources/startrolepayload.xml
new file mode 100644
index 0000000..4e82022
--- /dev/null
+++ b/labs/azure-management/src/test/resources/startrolepayload.xml
@@ -0,0 +1 @@
+<StartRoleOperation xmlns="http://schemas.microsoft.com/windowsazure" xmlns:i="http://www.w3.org/2001/XMLSchema-instance"><OperationType>StartRoleOperation</OperationType></StartRoleOperation>
\ No newline at end of file
diff --git a/labs/carrenza-vcloud-director/src/test/java/org/jclouds/carrenza/vcloud/director/CarrenzaVCloudDirectorHttpClientLiveTest.java b/labs/carrenza-vcloud-director/src/test/java/org/jclouds/carrenza/vcloud/director/CarrenzaVCloudDirectorHttpClientLiveTest.java
deleted file mode 100644
index f3959fa..0000000
--- a/labs/carrenza-vcloud-director/src/test/java/org/jclouds/carrenza/vcloud/director/CarrenzaVCloudDirectorHttpClientLiveTest.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/**
- * Licensed to jclouds, Inc. (jclouds) under one or more
- * contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  jclouds licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.jclouds.carrenza.vcloud.director;
-
-import org.jclouds.vcloud.director.v1_5.HttpClientLiveTest;
-import org.testng.annotations.Test;
-
-/**
- * {@inheritDoc}
- * 
- * @author danikov
- * @author grkvlt
- */
-@Test(groups = { "live", "user" }, singleThreaded = true, testName = "CarrenzaVCloudDirectorHttpClientLiveTest")
-public class CarrenzaVCloudDirectorHttpClientLiveTest extends HttpClientLiveTest {
-
-   public CarrenzaVCloudDirectorHttpClientLiveTest() {
-      provider = "carrenza-vcloud-director";
-   }
-}
diff --git a/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/CDMIApi.java b/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/CDMIApi.java
index f5a1650..5fcd3e6 100644
--- a/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/CDMIApi.java
+++ b/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/CDMIApi.java
@@ -24,6 +24,7 @@
 import org.jclouds.rest.annotations.Delegate;
 import org.jclouds.snia.cdmi.v1.features.ContainerApi;
 import org.jclouds.snia.cdmi.v1.features.DataApi;
+import org.jclouds.snia.cdmi.v1.features.DataNonCDMIContentTypeApi;
 import org.jclouds.snia.cdmi.v1.features.DomainApi;
 
 /**
@@ -54,4 +55,11 @@
     */
    @Delegate
    DataApi getDataApi();
+   
+   /**
+    * Provides synchronous access to Data Object Resource Operations.
+    */
+   @Delegate
+   DataNonCDMIContentTypeApi getDataNonCDMIContentTypeApi();
+
 }
diff --git a/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/CDMIAsyncApi.java b/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/CDMIAsyncApi.java
index f113142..a23670f 100644
--- a/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/CDMIAsyncApi.java
+++ b/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/CDMIAsyncApi.java
@@ -50,4 +50,11 @@
     */
    @Delegate
    DataAsyncApi getDataApi();
+
+   /**
+    * Provides asynchronous access to Data Object Resource Operations.
+    */
+   @Delegate
+   DataAsyncApi getDataNonCDMIContentTypeApi();
+   
 }
diff --git a/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/ObjectTypes.java b/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/ObjectTypes.java
index 8d93a0b..17e627b 100644
--- a/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/ObjectTypes.java
+++ b/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/ObjectTypes.java
@@ -21,11 +21,9 @@
 /**
  * Object Types used in CDMI.
  * 
- * @see javax.ws.rs.core.MediaType;
  */
 public interface ObjectTypes {
 
 	public static final String CONTAINER = "application/cdmi-container";
 	public static final String DATAOBJECT = "application/cdmi-object";
-	public static final String CDMIOBJECT = "application/cdmi-object";
 }
diff --git a/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/binders/BindQueryParmsToSuffix.java b/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/binders/BindQueryParmsToSuffix.java
new file mode 100644
index 0000000..d2fa4cf
--- /dev/null
+++ b/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/binders/BindQueryParmsToSuffix.java
@@ -0,0 +1,48 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.snia.cdmi.v1.binders;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+import javax.inject.Singleton;
+import org.jclouds.http.HttpRequest;
+import org.jclouds.rest.Binder;
+import org.jclouds.snia.cdmi.v1.queryparams.CDMIObjectQueryParams;
+
+/**
+ * This binding solves the problem jax-rs encoding ? ; : which some servers can
+ * not handle
+ * 
+ * @author Kenneth Nagin
+ */
+@Singleton
+public class BindQueryParmsToSuffix implements Binder {
+	@SuppressWarnings("unchecked")
+	@Override
+	public <R extends HttpRequest> R bindToRequest(R request, Object input) {
+		checkArgument(
+				checkNotNull(input, "input") instanceof CDMIObjectQueryParams,
+				"this binder is only valid for CDMIObjectQueryParams!");
+		checkNotNull(request, "request");
+		String queryParams = input.toString();
+		return (R) request.toBuilder()
+				.endpoint(request.getEndpoint() + "?" + queryParams).build();
+	}
+
+}
diff --git a/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/config/CDMIRestClientModule.java b/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/config/CDMIRestClientModule.java
index 865090a..2004e8c 100644
--- a/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/config/CDMIRestClientModule.java
+++ b/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/config/CDMIRestClientModule.java
@@ -32,6 +32,8 @@
 import org.jclouds.snia.cdmi.v1.features.ContainerApi;
 import org.jclouds.snia.cdmi.v1.features.DataAsyncApi;
 import org.jclouds.snia.cdmi.v1.features.DataApi;
+import org.jclouds.snia.cdmi.v1.features.DataNonCDMIContentTypeApi;
+import org.jclouds.snia.cdmi.v1.features.DataNonCDMIContentTypeAsyncApi;
 import org.jclouds.snia.cdmi.v1.features.DomainAsyncApi;
 import org.jclouds.snia.cdmi.v1.features.DomainApi;
 import org.jclouds.snia.cdmi.v1.handlers.CDMIErrorHandler;
@@ -48,7 +50,8 @@
 
    public static final Map<Class<?>, Class<?>> DELEGATE_MAP = ImmutableMap.<Class<?>, Class<?>> builder().put(
             DomainApi.class, DomainAsyncApi.class).put(ContainerApi.class, ContainerAsyncApi.class).put(
-            DataApi.class, DataAsyncApi.class).build();
+            DataApi.class, DataAsyncApi.class).put(
+                    DataNonCDMIContentTypeApi.class, DataNonCDMIContentTypeAsyncApi.class).build();
 
    public CDMIRestClientModule() {
       super(DELEGATE_MAP);
diff --git a/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/domain/DataObject.java b/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/domain/DataObject.java
index 3c0811b..f78ac12 100644
--- a/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/domain/DataObject.java
+++ b/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/domain/DataObject.java
@@ -159,6 +159,7 @@
 		Files.copy(getValueAsInputSupplier(), fileOut);
 		return fileOut;
 	}
+	
 
 	/**
 	 * get dataObject's value as a File
diff --git a/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/features/ContainerApi.java b/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/features/ContainerApi.java
index 6f005f4..728d99c 100644
--- a/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/features/ContainerApi.java
+++ b/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/features/ContainerApi.java
@@ -23,9 +23,10 @@
 import org.jclouds.concurrent.Timeout;
 import org.jclouds.snia.cdmi.v1.domain.Container;
 import org.jclouds.snia.cdmi.v1.options.CreateContainerOptions;
+import org.jclouds.snia.cdmi.v1.queryparams.ContainerQueryParams;
 
 /**
- * Container Object Resource Operations
+ * CDMI Container Object Resource Operations
  * 
  * @see ContainerAsyncApi
  * @author Kenneth Nagin
@@ -33,11 +34,81 @@
  */
 @Timeout(duration = 180, timeUnit = TimeUnit.SECONDS)
 public interface ContainerApi {
+
+	/**
+	 * get CDMI Container
+	 * 
+	 * @param containerName
+	 *            containerName must end with a forward slash, /.
+	 * @return Container
+	 *  <pre>
+	 *  Examples: 
+	 *  {@code
+	 *  container = getContainer("myContainer/");
+	 *  container = getContainer("parentContainer/childContainer/");
+	 *  }
+	 *  <pre>
+	 */
+	Container getContainer(String containerName);
+
+	/**
+	 * get CDMI Container
+	 * 
+	 * @param containerName
+	 * @param queryParams
+	 *            enables getting only certain fields, metadata, children range
+	 * @return Container
+	 * <pre>
+	 * Examples: 
+	 * {@code
+	 * container = getContainer("myContainer/",ContainerQueryParams.Builder.mimetype("text/plain").field("objectName"))
+	 * container = getContainer("myContainer/",ContainerQueryParams.Builder.metadata().field("objectName"))
+	 * }
+	 * </pre>
+	 * @see ContainerQueryParams 
+	 */
+	Container getContainer(String containerName,
+			ContainerQueryParams queryParams);
+
+	/**
+	 * Create CDMI Container
+	 * 
+	 * @param containerName
+	 *            containerName must end with a forward slash, /.
+	 * @return Container
+	 *  <pre>
+	 *  Examples: 
+	 *  {@code
+	 *  container = createContainer("myContainer/");
+	 *  container = createContainer("parentContainer/childContainer/");
+	 *  }
+	 *  </pre>
+	 */
+	Container createContainer(String containerName);
+
+	/**
+	 * Create CDMI Container
+	 * 
+	 * @param containerName
+	 * @param options
+	 *            enables adding metadata
+	 * @return Container
+	 *  <pre>
+	 *  Examples: 
+	 *  {@code
+	 *  container = createContainer("myContainer/",CreateContainerOptions.Builder..metadata(metaDataIn));
+	 *  }
+	 *  </pre>
+	 * @see CreateContainerOptions
+	 */
 	Container createContainer(String containerName,
 			CreateContainerOptions... options);
 
-	Container getContainer(String containerName);
-
+	/**
+	 * Delete CDMI Container
+	 * 
+	 * @param containerName
+	 */
 	void deleteContainer(String containerName);
 
 }
diff --git a/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/features/ContainerAsyncApi.java b/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/features/ContainerAsyncApi.java
index 83c6be2..84cec5f 100644
--- a/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/features/ContainerAsyncApi.java
+++ b/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/features/ContainerAsyncApi.java
@@ -26,61 +26,138 @@
 import javax.ws.rs.PathParam;
 import javax.ws.rs.Produces;
 import javax.ws.rs.core.MediaType;
-
-
-
+import org.jclouds.rest.annotations.BinderParam;
 import org.jclouds.rest.annotations.ExceptionParser;
 import org.jclouds.rest.annotations.Headers;
 import org.jclouds.rest.annotations.RequestFilters;
 import org.jclouds.rest.annotations.SkipEncoding;
 import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404;
 import org.jclouds.snia.cdmi.v1.ObjectTypes;
+import org.jclouds.snia.cdmi.v1.binders.BindQueryParmsToSuffix;
 import org.jclouds.snia.cdmi.v1.domain.Container;
 import org.jclouds.snia.cdmi.v1.filters.BasicAuthenticationAndTenantId;
 import org.jclouds.snia.cdmi.v1.filters.StripExtraAcceptHeader;
 import org.jclouds.snia.cdmi.v1.options.CreateContainerOptions;
-
+import org.jclouds.snia.cdmi.v1.queryparams.ContainerQueryParams;
 import com.google.common.util.concurrent.ListenableFuture;
 
 /**
- * Container Object Resource Operations
+ * CDMI Container Object Resource Operations
  * 
  * @see ContainerApi
  * @author Kenneth Nagin
  * @see <a href="http://www.snia.org/cdmi">api doc</a>
  */
-@SkipEncoding( { '/', '=' })
-@RequestFilters( { BasicAuthenticationAndTenantId.class, StripExtraAcceptHeader.class })
-@Headers(keys="X-CDMI-Specification-Version", values = "{jclouds.api-version}")
+@SkipEncoding({ '/', '=' })
+@RequestFilters({ BasicAuthenticationAndTenantId.class,
+		StripExtraAcceptHeader.class })
+@Headers(keys = "X-CDMI-Specification-Version", values = "{jclouds.api-version}")
 public interface ContainerAsyncApi {
 
-   /**
-    * @see ContainerApi#listContainers()
-    */
-   @GET
-   @Consumes( { ObjectTypes.CONTAINER, MediaType.APPLICATION_JSON })
-   @ExceptionParser(ReturnNullOnNotFoundOr404.class)
-   @Path("/{containerName}/")
-   ListenableFuture<Container> getContainer(@PathParam("containerName") String containerName);
-   
-   /**
-    * @see ContainerApi#createContainer
-    */
-   @PUT
-   @Consumes( { ObjectTypes.CONTAINER, MediaType.APPLICATION_JSON })
-   @Produces( { ObjectTypes.CONTAINER})
-   @ExceptionParser(ReturnNullOnNotFoundOr404.class)   
-   @Path("/{containerName}/")
-   ListenableFuture<Container> createContainer(@PathParam("containerName") String containerName,
-   					CreateContainerOptions... options);
+	/**
+	 * get CDMI Container
+	 * 
+	 * @param containerName
+	 *            containerName must end with a forward slash, /.
+	 * @return Container
+	 * 
+	 * <pre>
+	 *  Examples: 
+	 *  {@code
+	 *  container = getContainer("myContainer/");
+	 *  container = getContainer("parentContainer/childContainer/");
+	 * }
+	 * 
+	 * <pre>
+	 */
+	@GET
+	@Consumes({ ObjectTypes.CONTAINER, MediaType.APPLICATION_JSON })
+	@ExceptionParser(ReturnNullOnNotFoundOr404.class)
+	@Path("/{containerName}")
+	ListenableFuture<Container> getContainer(
+			@PathParam("containerName") String containerName);
 
-   /**
-    * @see ContainerApi#createContainer()
-    */
-   @DELETE
-   @Consumes( MediaType.APPLICATION_JSON )
-   @ExceptionParser(ReturnNullOnNotFoundOr404.class)
-   @Path("/{containerName}/")
-   ListenableFuture<Void> deleteContainer(@PathParam("containerName") String containerName);
+	/**
+	 * get CDMI Container
+	 * 
+	 * @param containerName
+	 * @param queryParams
+	 *            enables getting only certain fields, metadata, children range
+	 * @return Container
+	 * 
+	 * <pre>
+	 * Examples: 
+	 * {@code
+	 * container = getContainer("myContainer/",ContainerQueryParams.Builder.field("parentURI").field("objectName"))
+	 * container = getContainer("myContainer/",ContainerQueryParams.Builder.metadata().field("objectName"))
+	 * }
+	 * </pre>
+	 * @see ContainerQueryParams
+	 */
+	@GET
+	@Consumes({ ObjectTypes.CONTAINER, MediaType.APPLICATION_JSON })
+	@ExceptionParser(ReturnNullOnNotFoundOr404.class)
+	@Path("/{containerName}")
+	ListenableFuture<Container> getContainer(
+			@PathParam("containerName") String containerName,
+			@BinderParam(BindQueryParmsToSuffix.class) ContainerQueryParams queryParams);
+
+	/**
+	 * Create CDMI Container
+	 * 
+	 * @param containerName
+	 *            containerName must end with a forward slash, /.
+	 * @return Container
+	 *  <pre>
+	 *  Examples: 
+	 *  {@code
+	 *  container = createContainer("myContainer/");
+	 *  container = createContainer("parentContainer/childContainer/");
+	 *  }
+	 *  </pre>
+	 */
+	@PUT
+	@Consumes({ ObjectTypes.CONTAINER, MediaType.APPLICATION_JSON })
+	@Produces({ ObjectTypes.CONTAINER })
+	@ExceptionParser(ReturnNullOnNotFoundOr404.class)
+	@Path("/{containerName}")
+	ListenableFuture<Container> createContainer(
+			@PathParam("containerName") String containerName);
+
+	/**
+	 * Create CDMI Container
+	 * 
+	 * @param containerName
+	 * @param options
+	 *            enables adding metadata
+	 * @return Container
+	 *  <pre>
+	 *  Examples: 
+	 *  {@code
+	 *  container = createContainer("myContainer/",CreateContainerOptions.Builder..metadata(metaDataIn));
+	 *  }
+	 *  </pre>
+	 * @see CreateContainerOptions
+	 */
+	@PUT
+	@Consumes({ ObjectTypes.CONTAINER, MediaType.APPLICATION_JSON })
+	@Produces({ ObjectTypes.CONTAINER })
+	@ExceptionParser(ReturnNullOnNotFoundOr404.class)
+	@Path("/{containerName}")
+	ListenableFuture<Container> createContainer(
+			@PathParam("containerName") String containerName,
+			CreateContainerOptions... options);
+
+	/**
+	 * Delete Container
+	 * 
+	 * @param containerName
+	 */
+	@DELETE
+	@Consumes(MediaType.APPLICATION_JSON)
+	@ExceptionParser(ReturnNullOnNotFoundOr404.class)
+	@Path("/{containerName}")
+	ListenableFuture<Void> deleteContainer(
+			@PathParam("containerName") String containerName);
 
 }
diff --git a/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/features/DataApi.java b/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/features/DataApi.java
index 726205e..c85a945 100644
--- a/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/features/DataApi.java
+++ b/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/features/DataApi.java
@@ -21,8 +21,8 @@
 import java.util.concurrent.TimeUnit;
 import org.jclouds.concurrent.Timeout;
 import org.jclouds.snia.cdmi.v1.domain.DataObject;
-import org.jclouds.snia.cdmi.v1.options.CreateDataObjectNonCDMIOptions;
 import org.jclouds.snia.cdmi.v1.options.CreateDataObjectOptions;
+import org.jclouds.snia.cdmi.v1.queryparams.DataObjectQueryParams;
 
 /**
  * Data Object Resource Operations
@@ -33,15 +33,83 @@
  */
 @Timeout(duration = 180, timeUnit = TimeUnit.SECONDS)
 public interface DataApi {
+	/**
+	 * get CDMI Data object
+	 * 
+	 * @param containerName
+	 *            containerName must end with a forward slash, /.
+	 * @param  dataObjectName
+	 *            dataObjectName must not end with a forward slash, /.           
+	 * @return DataObject
+	 *  <pre>
+	 *  Examples: 
+	 *  {@code
+	 *  dataObject = getDataObject("myContainer/","myDataObject");
+	 *  dataObject = getDataObject("parentContainer/childContainer/","myDataObject");
+	 *  }
+	 *  <pre>
+	 */
+	DataObject getDataObject(String containerName, String dataObjectName);
+	/**
+	 * get CDMI Data object
+	 * 
+	 * @param containerName
+	 *            containerName must end with a forward slash, /.
+	 * @param dataObjectName
+	 *            dataObjectName must not end with a forward slash, /. 
+	 * @param queryParams 
+	 *            enables getting only certain fields, metadata, value range
+	 * @return DataObject
+	 *  <pre>
+	 *  Examples: 
+	 *  {@code
+	 *  dataObject = getContainer("myContainer/","myDataObject",ContainerQueryParams.Builder.field("parentURI").field("objectName"));
+	 *  dataObject = getContainer("myContainer/","myDataObject",ContainerQueryParams.Builder.value(0,10));
+	 *  }
+	 *  <pre>
+	 */
+	DataObject getDataObject(String containerName, String dataObjectName,
+			DataObjectQueryParams queryParams);
+
+	/**
+	 * create CDMI Data object
+	 * 
+	 * @param containerName
+	 *            containerName must end with a forward slash, /.
+	 * @param dataObjectName
+	 *            dataObjectName must not end with a forward slash, /. 
+	 * @param options 
+	 *            enables defining the body i.e. metadata, mimetype, value
+	 * @return DataObject
+	 *  <pre>
+	 *  Examples: 
+	 *  {@code
+	 *  dataObject = createDataObject("myContainer/",
+	 *                                "myDataObject",
+	 *                                CreateDataObjectOptions.Builder
+	 *                                                    .value(value)
+	 *                                                    .mimetype("text/plain")
+	 *                                                    .metadata(pDataObjectMetaDataIn);
+	 *  }
+	 *  <pre>
+	 */	
 	DataObject createDataObject(String containerName, String dataObjectName,
 			CreateDataObjectOptions... options);
-	 
-	void createDataObjectNonCDMI(String containerName, String dataObjectName, 
-			CreateDataObjectNonCDMIOptions... options );
 
-	DataObject getDataObject(String containerName, String dataObjectName);
-
+	/**
+	 * delete CDMI Data object
+	 * 
+	 * @param containerName
+	 *            containerName must end with a forward slash, /.
+	 * @param  dataObjectName
+	 *            dataObjectName must not end with a forward slash, /.           
+	 *  <pre>
+	 *  Examples: 
+	 *  {@code
+	 *  deleteDataObject("myContainer/","myDataObject");
+	 *  }
+	 *  <pre>
+	 */
 	void deleteDataObject(String containerName, String dataObjectName);
 
-
 }
diff --git a/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/features/DataAsyncApi.java b/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/features/DataAsyncApi.java
index af20549..7ae1216 100644
--- a/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/features/DataAsyncApi.java
+++ b/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/features/DataAsyncApi.java
@@ -27,17 +27,19 @@
 import javax.ws.rs.Produces;
 import javax.ws.rs.core.MediaType;
 
+import org.jclouds.rest.annotations.BinderParam;
 import org.jclouds.rest.annotations.ExceptionParser;
 import org.jclouds.rest.annotations.Headers;
 import org.jclouds.rest.annotations.RequestFilters;
 import org.jclouds.rest.annotations.SkipEncoding;
 import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404;
 import org.jclouds.snia.cdmi.v1.ObjectTypes;
+import org.jclouds.snia.cdmi.v1.binders.BindQueryParmsToSuffix;
 import org.jclouds.snia.cdmi.v1.domain.DataObject;
 import org.jclouds.snia.cdmi.v1.filters.BasicAuthenticationAndTenantId;
 import org.jclouds.snia.cdmi.v1.filters.StripExtraAcceptHeader;
-import org.jclouds.snia.cdmi.v1.options.CreateDataObjectNonCDMIOptions;
 import org.jclouds.snia.cdmi.v1.options.CreateDataObjectOptions;
+import org.jclouds.snia.cdmi.v1.queryparams.DataObjectQueryParams;
 
 import com.google.common.util.concurrent.ListenableFuture;
 
@@ -51,56 +53,56 @@
 @SkipEncoding({ '/', '=' })
 @RequestFilters({ BasicAuthenticationAndTenantId.class,
 		StripExtraAcceptHeader.class })
+@Headers(keys = "X-CDMI-Specification-Version", values = "{jclouds.api-version}")
 public interface DataAsyncApi {
 	/**
-	 * @see DataApi#getDataObject()
+	 * @see DataApi#getDataObject(String containerName, String dataObjectName)
 	 */
-	@Headers(keys = "X-CDMI-Specification-Version", values = "{jclouds.api-version}")
 	@GET
 	@Consumes({ ObjectTypes.DATAOBJECT, MediaType.APPLICATION_JSON })
 	@ExceptionParser(ReturnNullOnNotFoundOr404.class)
-	@Path("/{containerName}/{dataObjectName}")
+	@Path("/{containerName}{dataObjectName}")
 	ListenableFuture<DataObject> getDataObject(
 			@PathParam("containerName") String containerName,
 			@PathParam("dataObjectName") String dataObjectName);
 
 	/**
-	 * @see DataApi#createDataObject
+	 * @see DataApi#getDataObject(String containerName, String dataObjectName,
+	 *      DataObjectQueryParams queryParams)
 	 */
-	@Headers(keys = "X-CDMI-Specification-Version", values = "{jclouds.api-version}")
+	@GET
+	@Consumes({ ObjectTypes.DATAOBJECT, MediaType.APPLICATION_JSON })
+	@ExceptionParser(ReturnNullOnNotFoundOr404.class)
+	@Path("/{containerName}{dataObjectName}")
+	ListenableFuture<DataObject> getDataObject(
+			@PathParam("containerName") String containerName,
+			@PathParam("dataObjectName") String dataObjectName,
+			@BinderParam(BindQueryParmsToSuffix.class) DataObjectQueryParams queryParams);
+
+	/**
+	 * @see DataApi#createDataObject(String containerName, String
+	 *      dataObjectName, CreateDataObjectOptions... options)
+	 */
 	@PUT
 	@Consumes({ ObjectTypes.DATAOBJECT, MediaType.APPLICATION_JSON })
 	@Produces({ ObjectTypes.DATAOBJECT })
 	@ExceptionParser(ReturnNullOnNotFoundOr404.class)
-	@Path("/{containerName}/{dataObjectName}")
+	@Path("/{containerName}{dataObjectName}")
 	ListenableFuture<DataObject> createDataObject(
 			@PathParam("containerName") String containerName,
 			@PathParam("dataObjectName") String dataObjectName,
 			CreateDataObjectOptions... options);
 
 	/**
-	 * @see DataApi#createDataObjectNonCDMI
+	 * @see DataApi#deleteDataObject(String containerName, String
+	 *      dataObjectName)
 	 */
-	@PUT
-	@Consumes({ "text/plain" })
-	@Produces({ "text/plain;charset=utf-8" })
-	@ExceptionParser(ReturnNullOnNotFoundOr404.class)
-	@Path("/{containerName}/{dataObjectName}")
-	ListenableFuture<Void> createDataObjectNonCDMI(
-			@PathParam("containerName") String containerName,
-			@PathParam("dataObjectName") String dataObjectName,
-			CreateDataObjectNonCDMIOptions... options);
-
-	/**
-	 * @see DataApi#deleteDataObject()
-	 */
-	@Headers(keys = "X-CDMI-Specification-Version", values = "{jclouds.api-version}")
 	@DELETE
 	@Consumes(MediaType.TEXT_PLAIN)
 	// note: MediaType.APPLICATION_JSON work also, however without consumes
 	// jclouds throws null exception
 	@ExceptionParser(ReturnNullOnNotFoundOr404.class)
-	@Path("/{containerName}/{dataObjectName}")
+	@Path("/{containerName}{dataObjectName}")
 	ListenableFuture<Void> deleteDataObject(
 			@PathParam("containerName") String containerName,
 			@PathParam("dataObjectName") String dataObjectName);
diff --git a/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/features/DataNonCDMIContentTypeApi.java b/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/features/DataNonCDMIContentTypeApi.java
new file mode 100644
index 0000000..91b797f
--- /dev/null
+++ b/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/features/DataNonCDMIContentTypeApi.java
@@ -0,0 +1,204 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.snia.cdmi.v1.features;
+
+import java.util.concurrent.TimeUnit;
+import org.jclouds.concurrent.Timeout;
+import org.jclouds.io.Payload;
+import org.jclouds.snia.cdmi.v1.domain.DataObject;
+import org.jclouds.snia.cdmi.v1.queryparams.DataObjectQueryParams;
+
+/**
+ * Data Object Resource Operations
+ * 
+ * @see DataNonCDMIContentTypeAsyncApi
+ * @author Kenneth Nagin
+ * @see <a href="http://www.snia.org/cdmi">api doc</a>
+ */
+@Timeout(duration = 600, timeUnit = TimeUnit.SECONDS)
+public interface DataNonCDMIContentTypeApi {
+	/**
+	 * get CDMI Data object
+	 * 
+	 * @param containerName
+	 *            containerName must end with a forward slash, /.
+	 * @param dataObjectName
+	 *            dataObjectName must not end with a forward slash, /.
+	 * @return DataObjectNonCDMIContentType
+	 * 
+	 *         <pre>
+	 *  Examples: 
+	 *  {@code
+	 *  dataObject = getDataObject("myContainer/","myDataObject");
+	 *  dataObject = getDataObject("parentContainer/childContainer/","myDataObject");
+	 * }
+	 * 
+	 * <pre>
+	 * @see DataNonCDMIContentTypeAsyncApi#getDataObjectValue(String containerName, String dataObjectName)
+	 */
+	Payload getDataObjectValue(String containerName, String dataObjectName);
+
+	/**
+	 * get CDMI Data object
+	 * 
+	 * @param containerName
+	 *            containerName must end with a forward slash, /.
+	 * @param dataObjectName
+	 *            dataObjectName must not end with a forward slash, /.
+	 * @param range
+	 *            a valid ranges-specifier (see RFC2616 Section 14.35.1)
+	 * @return DataObjectNonCDMIContentType
+	 * 
+	 *         <pre>
+	 *  Examples: 
+	 *  {@code
+	 *  dataObject = getDataObject("myContainer/","myDataObject","bytes=0-10");
+	 * }
+	 * 
+	 *         <pre>
+	 */
+	Payload getDataObjectValue(String containerName, String dataObjectName,
+			String range);
+
+	/**
+	 * get CDMI Data object
+	 * 
+	 * @param containerName
+	 *            containerName must end with a forward slash, /.
+	 * @param dataObjectName
+	 *            dataObjectName must not end with a forward slash, /.
+	 * @param queryParams
+	 *            enables getting only certain fields, metadata, value range
+	 * @return DataObject
+	 * 
+	 *         <pre>
+	 *  Examples: 
+	 *  {@code
+	 *  dataObject = getContainer("myContainer/","myDataObject",ContainerQueryParams.Builder.field("parentURI").field("objectName"));
+	 *  dataObject = getContainer("myContainer/","myDataObject",ContainerQueryParams.Builder.value(0,10));
+	 * }
+	 * 
+	 *         <pre>
+	 */
+	DataObject getDataObject(String containerName, String dataObjectName,
+			DataObjectQueryParams queryParams);
+
+	/**
+	 * create CDMI Data object Non CDMI Content Type
+	 * 
+	 * @param containerName
+	 *            containerName must end with a forward slash, /.
+	 * @param dataObjectName
+	 *            dataObjectName must not end with a forward slash, /.
+	 * @param payload
+	 *            enables defining the body's payload i.e. file, inputStream,
+	 *            String, ByteArray
+	 * 
+	 *            <pre>
+	 *  Examples: 
+	 *  {@code
+	 *  createDataObject("myContainer/","myDataObject",new StringPayload("value");
+	 *  createDataObject("myContainer/","myDataObject",new ByteArrayPayload(bytes);
+	 *  createDataObject("myContainer/","myDataObject",new FilePayload(myFileIn);
+	 *  createDataObject("myContainer/","myDataObject",new InputStreamPayload(is);
+	 *  
+	 *  File f = new File("yellow-flowers.jpg");
+	 *  payloadIn = new InputStreamPayload(new FileInputStream(f));
+	 *  payloadIn.setContentMetadata(BaseMutableContentMetadata.fromContentMetadata(
+	 *            payloadIn.getContentMetadata().toBuilder()
+	 *            .contentType(MediaType.JPEG.toString())
+	 *            .contentLength(new Long(inFile.length()))
+	 *            .build()));
+	 *  dataNonCDMIContentTypeApi.createDataObject(containerName, f.getName(),
+	 * 					payloadIn);
+	 * }
+	 * 
+	 *            <pre>
+	 */
+	void createDataObject(String containerName, String dataObjectName,
+			Payload payload);
+
+	/**
+	 * create CDMI Data object partial Non CDMI Content Type Only part of the
+	 * object is contained in the payload and the X-CDMI-Partial header flag is
+	 * set to true
+	 * 
+	 * 
+	 * @param containerName
+	 *            containerName must end with a forward slash, /.
+	 * @param dataObjectName
+	 *            dataObjectName must not end with a forward slash, /.
+	 * @param payload
+	 *            enables defining the body's payload i.e. file, inputStream,
+	 *            String, ByteArray
+	 * 
+	 *            <pre>
+	 *  Examples: 
+	 *  {@code
+	 *  createDataObjectPartial("myContainer/","myDataObject",new StringPayload("value");
+	 *  createDataObjectPartial("myContainer/","myDataObject",new ByteArrayPayload(bytes);
+	 *  createDataObjectPartial("myContainer/","myDataObject",new FilePayload(myFileIn);
+	 *  createDataObjectPartial("myContainer/","myDataObject",new InputStreamPayload(is);
+	 * }
+	 * 
+	 *            <pre>
+	 */
+	void createDataObjectPartial(String containerName, String dataObjectName,
+			Payload payload);
+
+	/**
+	 * create CDMI Data object Non CDMI Content Type
+	 * 
+	 * @param containerName
+	 *            containerName must end with a forward slash, /.
+	 * @param dataObjectName
+	 *            dataObjectName must not end with a forward slash, /.
+	 * @param inputString
+	 *            simple string input
+	 * 
+	 *            <pre>
+	 *  Examples: 
+	 *  {@code
+	 *  createDataObject("myContainer/","myDataObject",new String("value");
+	 * }
+	 * 
+	 *            <pre>
+	 */
+	void createDataObject(String containerName, String dataObjectName,
+			String inputString);
+
+	/**
+	 * delete CDMI Data object
+	 * 
+	 * @param containerName
+	 *            containerName must end with a forward slash, /.
+	 * @param dataObjectName
+	 *            dataObjectName must not end with a forward slash, /.
+	 * 
+	 *            <pre>
+	 *  Examples: 
+	 *  {@code
+	 *  deleteDataObject("myContainer/","myDataObject");
+	 * }
+	 * 
+	 *            <pre>
+	 */
+	void deleteDataObject(String containerName, String dataObjectName);
+
+}
diff --git a/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/features/DataNonCDMIContentTypeAsyncApi.java b/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/features/DataNonCDMIContentTypeAsyncApi.java
new file mode 100644
index 0000000..f44630d
--- /dev/null
+++ b/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/features/DataNonCDMIContentTypeAsyncApi.java
@@ -0,0 +1,155 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.snia.cdmi.v1.features;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.HeaderParam;
+import javax.ws.rs.core.MediaType;
+import org.jclouds.rest.annotations.BinderParam;
+import org.jclouds.rest.annotations.ExceptionParser;
+import org.jclouds.rest.annotations.Headers;
+import org.jclouds.rest.annotations.PayloadParam;
+import org.jclouds.rest.annotations.RequestFilters;
+import org.jclouds.rest.annotations.ResponseParser;
+import org.jclouds.rest.annotations.SkipEncoding;
+import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404;
+import org.jclouds.snia.cdmi.v1.binders.BindQueryParmsToSuffix;
+import org.jclouds.snia.cdmi.v1.domain.DataObject;
+import org.jclouds.snia.cdmi.v1.filters.BasicAuthenticationAndTenantId;
+import org.jclouds.snia.cdmi.v1.filters.StripExtraAcceptHeader;
+import org.jclouds.snia.cdmi.v1.queryparams.DataObjectQueryParams;
+import org.jclouds.snia.cdmi.v1.functions.ParseObjectFromHeadersAndHttpContent;
+import com.google.common.util.concurrent.ListenableFuture;
+import org.jclouds.rest.annotations.Payload;
+
+/**
+ * Non CDMI Content Type Data Object Resource Operations
+ * 
+ * @see DataNonCDMIContentTypeApi
+ * @see DataAsyncApi
+ * @author Kenneth Nagin
+ * @see <a href="http://www.snia.org/cdmi">api doc</a>
+ */
+@SkipEncoding({ '/', '=' })
+@RequestFilters({ BasicAuthenticationAndTenantId.class,
+		StripExtraAcceptHeader.class })
+public interface DataNonCDMIContentTypeAsyncApi {
+	/**
+	 * @see DataNonCDMIContentTypeApi#getDataObjectValue(String containerName,
+	 *      String dataObjectName)
+	 */
+	@GET
+	@Consumes(MediaType.MEDIA_TYPE_WILDCARD)
+	@ResponseParser(ParseObjectFromHeadersAndHttpContent.class)
+	@ExceptionParser(ReturnNullOnNotFoundOr404.class)
+	@Path("/{containerName}{dataObjectName}")
+	ListenableFuture<org.jclouds.io.Payload> getDataObjectValue(
+			@PathParam("containerName") String containerName,
+			@PathParam("dataObjectName") String dataObjectName);
+
+	/**
+	 * @see DataNonCDMIContentTypeApi#getDataObjectValue(String containerName,
+	 *      String dataObjectName, String range )
+	 */
+
+	@GET
+	@Consumes(MediaType.MEDIA_TYPE_WILDCARD)
+	@ResponseParser(ParseObjectFromHeadersAndHttpContent.class)
+	@ExceptionParser(ReturnNullOnNotFoundOr404.class)
+	@Path("/{containerName}{dataObjectName}")
+	ListenableFuture<org.jclouds.io.Payload> getDataObjectValue(
+			@PathParam("containerName") String containerName,
+			@PathParam("dataObjectName") String dataObjectName,
+			@HeaderParam("Range") String range);
+
+	/**
+	 * @see DataNonCDMIContentTypeApi#getDataObject(String containerName, String
+	 *      dataObjectName, DataObjectQueryParams queryParams )
+	 */
+	@GET
+	@Consumes(MediaType.APPLICATION_JSON)
+	@ExceptionParser(ReturnNullOnNotFoundOr404.class)
+	@Path("/{containerName}{dataObjectName}")
+	ListenableFuture<DataObject> getDataObject(
+			@PathParam("containerName") String containerName,
+			@PathParam("dataObjectName") String dataObjectName,
+			@BinderParam(BindQueryParmsToSuffix.class) DataObjectQueryParams queryParams);
+
+	/**
+	 * @see DataNonCDMIContentTypeApi#createDataObject(String containerName,
+	 *      String dataObjectName, org.jclouds.io.Payload payload )
+	 */
+	@PUT
+	@Consumes(MediaType.MEDIA_TYPE_WILDCARD)
+	@ExceptionParser(ReturnNullOnNotFoundOr404.class)
+	@Path("/{containerName}{dataObjectName}")
+	ListenableFuture<Void> createDataObject(
+			@PathParam("containerName") String containerName,
+			@PathParam("dataObjectName") String dataObjectName,
+			org.jclouds.io.Payload payload);
+
+	/**
+	 * @see DataNonCDMIContentTypeApi#createDataObjectPartial(String
+	 *      containerName, String dataObjectName, org.jclouds.io.Payload payload
+	 *      )
+	 */
+	@PUT
+	@Consumes(MediaType.MEDIA_TYPE_WILDCARD)
+	@ExceptionParser(ReturnNullOnNotFoundOr404.class)
+	@Path("/{containerName}{dataObjectName}")
+	@Headers(keys = "X-CDMI-Partial", values = "true")
+	ListenableFuture<Void> createDataObjectPartial(
+			@PathParam("containerName") String containerName,
+			@PathParam("dataObjectName") String dataObjectName,
+			org.jclouds.io.Payload payload);
+
+	/**
+	 * @see DataNonCDMIContentTypeApi#createDataObject(String containerName,
+	 *      String dataObjectName, String input )
+	 */
+	@PUT
+	@Consumes(MediaType.MEDIA_TYPE_WILDCARD)
+	@Produces(MediaType.TEXT_PLAIN)
+	@ExceptionParser(ReturnNullOnNotFoundOr404.class)
+	@Path("/{containerName}{dataObjectName}")
+	@Payload("{input}")
+	ListenableFuture<Void> createDataObject(
+			@PathParam("containerName") String containerName,
+			@PathParam("dataObjectName") String dataObjectName,
+			@PayloadParam("input") String input);
+
+	/**
+	 * @see DataNonCDMIContentTypeApi#deleteDataObject(String containerName,
+	 *      String dataObjectName)
+	 */
+	@DELETE
+	@Consumes(MediaType.MEDIA_TYPE_WILDCARD)
+	@ExceptionParser(ReturnNullOnNotFoundOr404.class)
+	@Path("/{containerName}{dataObjectName}")
+	ListenableFuture<Void> deleteDataObject(
+			@PathParam("containerName") String containerName,
+			@PathParam("dataObjectName") String dataObjectName);
+
+}
diff --git a/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/functions/ParseObjectFromHeadersAndHttpContent.java b/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/functions/ParseObjectFromHeadersAndHttpContent.java
new file mode 100644
index 0000000..631b584
--- /dev/null
+++ b/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/functions/ParseObjectFromHeadersAndHttpContent.java
@@ -0,0 +1,46 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.snia.cdmi.v1.functions;
+
+import org.jclouds.http.HttpRequest;
+import org.jclouds.http.HttpResponse;
+import org.jclouds.io.Payload;
+import org.jclouds.rest.InvocationContext;
+
+import com.google.common.base.Function;
+
+/**
+ * Parses payload from HTTP response .
+ * 
+ * @author Kenneth Nagin
+ */
+public class ParseObjectFromHeadersAndHttpContent implements
+		Function<HttpResponse, Payload>,
+		InvocationContext<ParseObjectFromHeadersAndHttpContent> {
+
+	public Payload apply(HttpResponse from) {
+		Payload object = from.getPayload();
+		return object;
+	}
+
+	@Override
+	public ParseObjectFromHeadersAndHttpContent setContext(HttpRequest request) {
+		return this;
+	}
+}
diff --git a/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/options/CreateCDMIObjectOptions.java b/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/options/CreateCDMIObjectOptions.java
new file mode 100644
index 0000000..47ca431
--- /dev/null
+++ b/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/options/CreateCDMIObjectOptions.java
@@ -0,0 +1,41 @@
+package org.jclouds.snia.cdmi.v1.options;

+

+import java.util.Map;

+import java.util.Map.Entry;

+

+import org.jclouds.http.options.BaseHttpRequestOptions;

+

+import com.google.gson.JsonObject;

+

+/**

+ * Contains options supported in the REST API for the CREATE container

+ * operation. <h2>

+ * 

+ * @author Kenneth Nagin

+ */

+public class CreateCDMIObjectOptions extends BaseHttpRequestOptions {

+	protected JsonObject jsonObjectBody = new JsonObject();

+	/**

+	 * A name-value pair to associate with the container as metadata.

+	 */

+	public CreateCDMIObjectOptions metadata(Map<String, String> metadata) {

+		JsonObject jsonObjectMetadata = new JsonObject();

+		if (metadata != null) {

+			for (Entry<String, String> entry : metadata.entrySet()) {

+				jsonObjectMetadata

+						.addProperty(entry.getKey(), entry.getValue());

+			}

+		}

+		jsonObjectBody.add("metadata", jsonObjectMetadata);

+		this.payload = jsonObjectBody.toString();

+		return this;		

+	}

+

+	public static class Builder {

+		public static CreateCDMIObjectOptions withMetadata(

+				Map<String, String> metadata) {

+			CreateCDMIObjectOptions options = new CreateCDMIObjectOptions();

+			return (CreateCDMIObjectOptions) options.metadata(metadata);

+		}

+	}

+}

diff --git a/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/options/CreateContainerOptions.java b/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/options/CreateContainerOptions.java
index 5c8050b..39d60c7 100644
--- a/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/options/CreateContainerOptions.java
+++ b/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/options/CreateContainerOptions.java
@@ -1,39 +1,26 @@
 package org.jclouds.snia.cdmi.v1.options;

 

 import java.util.Map;

-import java.util.Map.Entry;

-

-import org.jclouds.http.options.BaseHttpRequestOptions;

 

 /**

- * Contains options supported in the REST API for the CREATE container

- * operation. <h2>

+ * Optional Create CDMI Contain options

  * 

  * @author Kenneth Nagin

  */

-public class CreateContainerOptions extends BaseHttpRequestOptions {

+public class CreateContainerOptions extends CreateCDMIObjectOptions {

 	/**

 	 * A name-value pair to associate with the container as metadata.

 	 */

-	public CreateContainerOptions withMetadata(Map<String, String> metadata) {

-		String s = "{ \"metadata\" : {\"key1\" : \"value1\",\"key2\" : \"value2\"} }";

-		this.payload = s;

-		String payload = "{ \"metadata\" : {";

-		String separator = " ";

-		for (Entry<String, String> entry : metadata.entrySet()) {

-			payload = payload + separator + "\"" + entry.getKey() + "\" : \""

-					+ entry.getValue() + "\"";

-			separator = ",";

-		}

-		this.payload = payload + "} }";

+	public CreateContainerOptions metadata(Map<String, String> metadata) {

+		super.metadata(metadata);

 		return this;

+		

 	}

-

 	public static class Builder {

-		public static CreateContainerOptions withMetadata(

+		public static CreateContainerOptions metadata(

 				Map<String, String> metadata) {

 			CreateContainerOptions options = new CreateContainerOptions();

-			return (CreateContainerOptions) options.withMetadata(metadata);

+			return (CreateContainerOptions) options.metadata(metadata);

 		}

 	}

 }

diff --git a/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/options/CreateDataObjectOptions.java b/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/options/CreateDataObjectOptions.java
index 6f0905b..b0738fb 100644
--- a/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/options/CreateDataObjectOptions.java
+++ b/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/options/CreateDataObjectOptions.java
@@ -7,12 +7,8 @@
 import java.io.InputStreamReader;

 import java.io.IOException;

 import java.util.Map;

-import java.util.Map.Entry;

-

-import org.jclouds.http.options.BaseHttpRequestOptions;

 import com.google.common.base.Charsets;

 import java.nio.charset.Charset;

-import com.google.gson.JsonObject;

 import com.google.common.io.CharStreams;

 import com.google.common.io.Files;

 

@@ -22,8 +18,7 @@
  * 

  * @author Kenneth Nagin

  */

-public class CreateDataObjectOptions extends BaseHttpRequestOptions {

-	private JsonObject jsonObjectBody = new JsonObject();

+public class CreateDataObjectOptions extends CreateCDMIObjectOptions {

 

 	public CreateDataObjectOptions() {

 		jsonObjectBody.addProperty("value", new String());

@@ -33,18 +28,10 @@
 	 * Create CDMI data object with metadata

 	 * 

 	 * @param metadata

-	 * @return this

+	 * @return CreateDataObjectOptions

 	 */

 	public CreateDataObjectOptions metadata(Map<String, String> metadata) {

-		JsonObject jsonObjectMetadata = new JsonObject();

-		if (metadata != null) {

-			for (Entry<String, String> entry : metadata.entrySet()) {

-				jsonObjectMetadata

-						.addProperty(entry.getKey(), entry.getValue());

-			}

-		}

-		jsonObjectBody.add("metadata", jsonObjectMetadata);

-		this.payload = jsonObjectBody.toString();

+		super.metadata(metadata);

 		return this;

 	}

 

@@ -52,7 +39,7 @@
 	 * Create CDMI data object with mimetype

 	 * 

 	 * @param mimetype

-	 * @return

+	 * @return CreateDataObjectOptions

 	 */

 	public CreateDataObjectOptions mimetype(String mimetype) {

 		jsonObjectBody.addProperty("mimetype", mimetype);

@@ -63,7 +50,7 @@
 	/**

 	 * Create CDMI data object with value equal to empty string

 	 * 

-	 * @return

+	 * @return CreateDataObjectOptions

 	 */

 	public CreateDataObjectOptions value() {

 		this.payload = jsonObjectBody.toString();

@@ -75,7 +62,7 @@
 	 * 

 	 * @param value

 	 *            String value

-	 * @return

+	 * @return CreateDataObjectOptions

 	 */

 	public CreateDataObjectOptions value(String value) {

 		jsonObjectBody.addProperty("value", (value == null) ? new String()

@@ -89,7 +76,7 @@
 	 * 

 	 * @param value

 	 *            byte array value byte array is converted to a String value

-	 * @return

+	 * @return CreateDataObjectOptions

 	 */

 	public CreateDataObjectOptions value(byte[] value) throws IOException {

 		jsonObjectBody.addProperty("value",

@@ -104,7 +91,7 @@
 	 * 

 	 * @param value

 	 *            File File is converted to a String value with charset UTF_8

-	 * @return

+	 * @return CreateDataObjectOptions

 	 */

 	public CreateDataObjectOptions value(File value) throws IOException {

 		jsonObjectBody.addProperty("value", (value == null) ? new String()

@@ -120,7 +107,7 @@
 	 *            File

 	 * @param charset

 	 *            character set of file File is converted to a String value

-	 * @return

+	 * @return CreateDataObjectOptions

 	 */

 	public CreateDataObjectOptions value(File value, Charset charset)

 			throws IOException {

@@ -136,7 +123,7 @@
 	 * @param value

 	 *            InputSteam InputSteam is converted to a String value with

 	 *            charset UTF_8

-	 * @return

+	 * @return CreateDataObjectOptions

 	 */

 	public CreateDataObjectOptions value(InputStream value) throws IOException {

 		jsonObjectBody

@@ -157,7 +144,7 @@
 	 * @param charset

 	 *            character set of input stream InputSteam is converted to a

 	 *            String value with charset UTF_8

-	 * @return

+	 * @return CreateDataObjectOptions

 	 */

 	public CreateDataObjectOptions value(InputStream value, Charset charset)

 			throws IOException {

diff --git a/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/options/GetCDMIObjectOptions.java b/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/options/GetCDMIObjectOptions.java
new file mode 100644
index 0000000..0a36e15
--- /dev/null
+++ b/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/options/GetCDMIObjectOptions.java
@@ -0,0 +1,82 @@
+package org.jclouds.snia.cdmi.v1.options;

+

+import org.jclouds.http.options.BaseHttpRequestOptions;

+

+/**

+ * Optional get CDMI object options Note: We use

+ * BaseHttpRequestOptions.pathSuffix to include the CDMI query parameters rather

+ * than queryParam or MatrixParam because the CDMI specification is not

+ * following the standard usage. This is the summary of the CDMI specification:

+ * To read one or more requested fields from an existing CDMI container object,

+ * one of the following requests shall be performed: 

+ * GET <root URI>/<ContainerName>/<TheContainerName>/?<fieldname>;<fieldname>;... 

+ * GET <root URI>/<ContainerName>/<TheContainerName>/?children:<range>;... 

+ * GET <root URI>/<ContainerName>/<TheContainerName>/?metadata:<prefix>;...

+ * 

+ * For example: GET /MyContainer/?parentURI;children HTTP/1.1 

+ * GET /MyContainer/?childrenrange;children:0-2 HTTP/1.1

+ * 

+ * To read one or more requested fields from an existing data object, one of the

+ * following requests shall be performed: 

+ * GET <root URI>/<ContainerName>/<DataObjectName>?<fieldname>;<fieldname>;... 

+ * GET <root URI>/<ContainerName>/<DataObjectName>?value:<range>;... 

+ * GET <root URI>/<ContainerName>/<DataObjectName>?metadata:<prefix>;...

+ * 

+ * @author Kenneth Nagin

+ */

+public class GetCDMIObjectOptions extends BaseHttpRequestOptions {

+

+	public GetCDMIObjectOptions() {

+		this.pathSuffix = "?";

+	}

+

+	/**

+	 * Get CDMI data object's field

+	 * 

+	 * @param fieldname

+	 * @return this

+	 */

+	public GetCDMIObjectOptions field(String fieldname) {

+		this.pathSuffix = this.pathSuffix + fieldname + ";";

+		return this;

+	}

+

+	/**

+	 * Get CDMI data object's metadata

+	 * 

+	 * @return this

+	 */

+	public GetCDMIObjectOptions metadata() {

+		this.pathSuffix = this.pathSuffix + "metadata;";

+		return this;

+	}

+

+	/**

+	 * Get CDMI data object's metadata

+	 * 

+	 * @param prefix

+	 * @return this

+	 */

+	public GetCDMIObjectOptions metadata(String prefix) {

+		this.pathSuffix = this.pathSuffix + "metadata:" + prefix + ";";

+		return this;

+	}

+

+	public static class Builder {

+		public static GetCDMIObjectOptions field(String fieldname) {

+			GetCDMIObjectOptions options = new GetCDMIObjectOptions();

+			return (GetCDMIObjectOptions) options.field(fieldname);

+		}

+

+		public static GetCDMIObjectOptions metadata() {

+			GetCDMIObjectOptions options = new GetCDMIObjectOptions();

+			return (GetCDMIObjectOptions) options.metadata();

+		}

+

+		public static GetCDMIObjectOptions metadata(String prefix) {

+			GetCDMIObjectOptions options = new GetCDMIObjectOptions();

+			return (GetCDMIObjectOptions) options.metadata(prefix);

+		}

+

+	}

+}

diff --git a/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/options/GetContainerOptions.java b/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/options/GetContainerOptions.java
new file mode 100644
index 0000000..105ffc1
--- /dev/null
+++ b/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/options/GetContainerOptions.java
@@ -0,0 +1,96 @@
+package org.jclouds.snia.cdmi.v1.options;

+

+

+/**

+ * Optional get CDMI container operations

+ * 

+ * @author Kenneth Nagin

+ */

+public class GetContainerOptions extends GetCDMIObjectOptions {

+

+	public GetContainerOptions() {

+		super();

+	}

+

+	/**

+	 * Get CDMI container's field

+	 * 

+	 * @param fieldname

+	 * @return this

+	 */

+	public GetContainerOptions field(String fieldname) {

+		super.field(fieldname);

+		return this;

+	}

+

+	/**

+	 * Get CDMI container's metadata

+	 * 

+	 * @return this

+	 */

+	public GetContainerOptions metadata() {

+		super.metadata();

+		return this;

+	}

+

+	/**

+	 * Get CDMI container's metadata

+	 * 

+	 * @param prefix

+	 * @return this

+	 */

+	public GetContainerOptions metadata(String prefix) {

+		super.metadata(prefix);

+		return this;

+	}

+

+	/**

+	 * Get CDMI container's children

+	 * 

+	 * @return this

+	 */

+	public GetContainerOptions children() {

+		this.pathSuffix = this.pathSuffix + "children;";

+		return this;

+	}

+

+	/**

+	 * Get CDMI container's children in range

+	 * 

+	 * @param from

+	 * @param to

+	 * @return this

+	 */

+	public GetContainerOptions children(int from, int to) {

+		this.pathSuffix = this.pathSuffix + "children:" + from + "-" + to + ";";

+		return this;

+	}

+

+	public static class Builder {

+		public static GetContainerOptions field(String fieldname) {

+			GetContainerOptions options = new GetContainerOptions();

+			return (GetContainerOptions) options.field(fieldname);

+		}

+

+		public static GetContainerOptions metadata() {

+			GetContainerOptions options = new GetContainerOptions();

+			return (GetContainerOptions) options.metadata();

+		}

+

+		public static GetContainerOptions metadata(String prefix) {

+			GetContainerOptions options = new GetContainerOptions();

+			return (GetContainerOptions) options.metadata(prefix);

+		}

+

+		public static GetContainerOptions children() {

+			GetContainerOptions options = new GetContainerOptions();

+			return (GetContainerOptions) options.children();

+		}

+

+		public static GetContainerOptions children(int from, int to) {

+			GetContainerOptions options = new GetContainerOptions();

+			return (GetContainerOptions) options.children(from, to);

+		}

+

+	}

+}

diff --git a/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/queryparams/CDMIObjectQueryParams.java b/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/queryparams/CDMIObjectQueryParams.java
new file mode 100644
index 0000000..c55bc59
--- /dev/null
+++ b/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/queryparams/CDMIObjectQueryParams.java
@@ -0,0 +1,80 @@
+package org.jclouds.snia.cdmi.v1.queryparams;

+

+

+

+import java.util.HashMap;

+

+import org.jclouds.http.options.BaseHttpRequestOptions;

+

+import com.google.common.collect.Multimap;

+

+/**

+ * Generate CDMI object query parameters 

+ * Note:  The preferred implementation would use jax-rs queryParam.

+ * However, the CDMI query parameters specification does not conform to 

+ * jax-rs queryParam of key=value separated by &.

+ * Rather it follows the form:

+ * ?<fieldname>;<fieldname>;.... 

+ * ?metadata:<prefix>;...

+ * ?children:<from>-<to>;...

+ * ?value:<from>-<to>;...

+ * 

+ * @author Kenneth Nagin

+ */

+public class CDMIObjectQueryParams  {	

+	

+	protected String queryParams = "";

+	

+	public CDMIObjectQueryParams() {

+		super();

+	}

+

+	/**

+	 * Get CDMI data object's field value

+	 * @param fieldname

+	 * @return this

+	 */

+	public CDMIObjectQueryParams field(String fieldname) {

+		queryParams = queryParams + fieldname + ";";

+		return this;	

+	}

+	

+	/**

+	 * Get CDMI data object's metadata

+	 * @return this

+	 */

+	public CDMIObjectQueryParams metadata() {

+		queryParams = queryParams + "metadata;";

+		return this;

+	}

+

+	/**

+	 * Get CDMI data object's metadata associated with prefix

+	 * @param prefix

+	 * @return this

+	 */

+	public CDMIObjectQueryParams metadata(String prefix) {

+		queryParams = queryParams + "metadata:"+prefix+";";

+		return this;

+	}

+	

+

+	public static class Builder {

+		public static CDMIObjectQueryParams field(

+				String fieldname) {

+			CDMIObjectQueryParams options = new CDMIObjectQueryParams();

+			return (CDMIObjectQueryParams) options.field(fieldname);

+		}

+		public static CDMIObjectQueryParams metadata(

+				String prefix) {

+			CDMIObjectQueryParams options = new CDMIObjectQueryParams();

+			return (CDMIObjectQueryParams) options.metadata(prefix);

+		}

+

+	}

+	

+	public String toString () {

+		return queryParams;

+	}

+	

+}

diff --git a/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/queryparams/ContainerQueryParams.java b/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/queryparams/ContainerQueryParams.java
new file mode 100644
index 0000000..0501940
--- /dev/null
+++ b/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/queryparams/ContainerQueryParams.java
@@ -0,0 +1,96 @@
+package org.jclouds.snia.cdmi.v1.queryparams;

+

+/**

+ * Generate CDMI container query parameters 

+ * Example:

+ *   container = containerApi.getContainer(containerName,ContainerQueryParams.Builder.field("parentURI"));

+ *   container = containerApi.getContainer(containerName,ContainerQueryParams.Builder.children(0,3));

+ * 

+ * @author Kenneth Nagin

+ */

+public class ContainerQueryParams extends CDMIObjectQueryParams {	

+

+	public ContainerQueryParams() {

+		super();

+	}

+

+	/**

+	 * Get CDMI container's field value

+	 * @param fieldname

+	 * @return this

+	 */

+	public ContainerQueryParams field(String fieldname) {

+		super.field(fieldname);

+		return this;	

+	}

+	

+	/**

+	 * Get CDMI container's metadata

+	 * @return this

+	 */

+	public ContainerQueryParams metadata() {

+		super.metadata();

+		return this;

+	}

+

+	/**

+	 * Get CDMI container's metadata associated with prefix

+	 * @param prefix

+	 * @return this

+	 */

+	public ContainerQueryParams metadata(String prefix) {

+		super.metadata(prefix);

+		return this;

+	}

+	

+	/**

+	 * Get CDMI container's children

+	 * @return this

+	 */

+	public ContainerQueryParams children() {

+		queryParams = queryParams + "children;";

+		return this;

+	}

+	

+	

+	/**

+	 * Get CDMI container's children within range

+	 * @param from

+	 * @param to

+	 * @return this

+	 */

+	public ContainerQueryParams children(int from, int to) {

+		queryParams = queryParams + "children:"+from+"-"+to+";";

+		return this;

+	}

+

+

+	public static class Builder {

+		public static ContainerQueryParams field(

+				String fieldname) {

+			ContainerQueryParams options = new ContainerQueryParams();

+			return (ContainerQueryParams) options.field(fieldname);

+		}

+		public static ContainerQueryParams metadata() {

+			ContainerQueryParams options = new ContainerQueryParams();

+			return (ContainerQueryParams) options.metadata();

+		}

+		

+		public static ContainerQueryParams metadata(

+				String prefix) {

+			ContainerQueryParams options = new ContainerQueryParams();

+			return (ContainerQueryParams) options.metadata(prefix);

+		}

+		public static ContainerQueryParams children() {

+			ContainerQueryParams options = new ContainerQueryParams();

+			return (ContainerQueryParams) options.children();

+		}

+		public static ContainerQueryParams children(

+					int from, int to) {

+				ContainerQueryParams options = new ContainerQueryParams();

+				return (ContainerQueryParams) options.children(from,to);

+		}

+

+	}

+	

+}

diff --git a/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/queryparams/DataObjectQueryParams.java b/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/queryparams/DataObjectQueryParams.java
new file mode 100644
index 0000000..e70107f
--- /dev/null
+++ b/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/queryparams/DataObjectQueryParams.java
@@ -0,0 +1,103 @@
+package org.jclouds.snia.cdmi.v1.queryparams;

+

+

+

+import java.util.HashMap;

+

+import org.jclouds.http.options.BaseHttpRequestOptions;

+

+import com.google.common.collect.Multimap;

+

+/**

+ * Generate CDMI data object query parameters 

+ * Example:

+ *   dataObject = dataApi.getDataObject(containerName,dataObjectNameIn,DataObjectQueryParams.Builder.field("parentURI"));

+ *   dataObject = dataApi.getDataObject(containerName,dataObjectNameIn,DataObjectQueryParams.Builder.value());

+ * 

+ * @author Kenneth Nagin

+ */

+public class DataObjectQueryParams extends CDMIObjectQueryParams {	

+

+	public DataObjectQueryParams() {

+		super();

+	}

+

+	/**

+	 * Get CDMI data object's field value

+	 * @param fieldname

+	 * @return this

+	 */

+	public DataObjectQueryParams field(String fieldname) {

+		super.field(fieldname);

+		return this;	

+	}

+	

+	/**

+	 * Get CDMI data object's metadata

+	 * @return this

+	 */

+	public DataObjectQueryParams metadata() {

+		super.metadata();

+		return this;

+	}

+

+	/**

+	 * Get CDMI data object's metadata associated with prefix

+	 * @param prefix

+	 * @return this

+	 */

+	public DataObjectQueryParams metadata(String prefix) {

+		super.metadata(prefix);

+		return this;

+	}

+	

+	/**

+	 * Get CDMI data object's value with range

+	 * @return this

+	 */

+	public DataObjectQueryParams value() {

+		queryParams = queryParams + "value;";

+		return this;

+	}

+	

+	

+	/**

+	 * Get CDMI data object's value within range

+	 * @param from

+	 * @param to

+	 * @return this

+	 */

+	public DataObjectQueryParams value(int from, int to) {

+		queryParams = queryParams + "value:"+from+"-"+to+";";

+		return this;

+	}

+

+

+	public static class Builder {

+		public static DataObjectQueryParams field(

+				String fieldname) {

+			DataObjectQueryParams options = new DataObjectQueryParams();

+			return (DataObjectQueryParams) options.field(fieldname);

+		}

+		public static DataObjectQueryParams metadata() {

+			DataObjectQueryParams options = new DataObjectQueryParams();

+			return (DataObjectQueryParams) options.metadata();

+		}

+		public static DataObjectQueryParams metadata(

+				String prefix) {

+			DataObjectQueryParams options = new DataObjectQueryParams();

+			return (DataObjectQueryParams) options.metadata(prefix);

+		}

+		public static DataObjectQueryParams value() {

+			DataObjectQueryParams options = new DataObjectQueryParams();

+			return (DataObjectQueryParams) options.value();

+		}

+		public static DataObjectQueryParams value(

+					int from, int to) {

+				DataObjectQueryParams options = new DataObjectQueryParams();

+				return (DataObjectQueryParams) options.value(from,to);

+		}

+

+	}

+	

+}

diff --git a/labs/cdmi/src/test/java/org/jclouds/snia/cdmi/v1/features/ContainerApiExpectTest.java b/labs/cdmi/src/test/java/org/jclouds/snia/cdmi/v1/features/ContainerApiExpectTest.java
index 60df803..82a23c9 100644
--- a/labs/cdmi/src/test/java/org/jclouds/snia/cdmi/v1/features/ContainerApiExpectTest.java
+++ b/labs/cdmi/src/test/java/org/jclouds/snia/cdmi/v1/features/ContainerApiExpectTest.java
@@ -58,7 +58,7 @@
       CDMIApi apiWhenContainersExist = requestSendsResponse(getContainer, getContainerResponse);
 
       assertEquals(
-            apiWhenContainersExist.getContainerApi().getContainer("MyContainer"),
+            apiWhenContainersExist.getContainerApi().getContainer("MyContainer/"),
             new ParseContainerTest().expected());
    }
    
diff --git a/labs/cdmi/src/test/java/org/jclouds/snia/cdmi/v1/features/ContainerApiLiveTest.java b/labs/cdmi/src/test/java/org/jclouds/snia/cdmi/v1/features/ContainerApiLiveTest.java
index a6d5128..53bfe15 100644
--- a/labs/cdmi/src/test/java/org/jclouds/snia/cdmi/v1/features/ContainerApiLiveTest.java
+++ b/labs/cdmi/src/test/java/org/jclouds/snia/cdmi/v1/features/ContainerApiLiveTest.java
@@ -32,6 +32,7 @@
 import org.jclouds.snia.cdmi.v1.domain.Container;
 import org.jclouds.snia.cdmi.v1.internal.BaseCDMIApiLiveTest;
 import org.jclouds.snia.cdmi.v1.options.CreateContainerOptions;
+import org.jclouds.snia.cdmi.v1.queryparams.ContainerQueryParams;
 import org.testng.annotations.Test;
 
 /**
@@ -44,69 +45,245 @@
 
 	@Test
 	public void testCreateContainer() throws Exception {
-		String pContainerName = "MyContainer" + System.currentTimeMillis();
+		String pContainerName = "MyContainer" + System.currentTimeMillis() + "/";
+		Map<String, String> pContainerMetaDataIn = new HashMap<String, String>();
+		Iterator<String> keys;
+		pContainerMetaDataIn.put("containerkey1", "value1");
+		pContainerMetaDataIn.put("containerkey2", "value2");
+		pContainerMetaDataIn.put("containerkey3", "value3");
+
+		CreateContainerOptions pCreateContainerOptions = CreateContainerOptions.Builder
+				.metadata(pContainerMetaDataIn);
+		ContainerApi api = cdmiContext.getApi().getContainerApi();
+
+		Logger.getAnonymousLogger().info("createContainer: " + pContainerName);
+
+		Container container = api.createContainer(pContainerName,
+				pCreateContainerOptions);
+		assertNotNull(container);
+		try {
+			System.out.println(container);
+			Logger.getAnonymousLogger().info("getContainer: " + pContainerName);
+			container = api.getContainer(pContainerName);
+			assertNotNull(container);
+			System.out.println(container);
+			assertEquals(container.getObjectType(), ObjectTypes.CONTAINER);
+			assertNotNull(container.getObjectID());
+			assertNotNull(container.getObjectName());
+			assertEquals(container.getObjectName(), pContainerName);
+			assertEquals(container.getParentURI(), "/");
+			assertNotNull(container.getChildren());
+			assertEquals(container.getChildren().isEmpty(), true);
+			System.out.println("Children: " + container.getChildren());
+			assertNotNull(container.getMetadata());
+			System.out.println("Raw metadata: " + container.getMetadata());
+			keys = container.getMetadata().keySet().iterator();
+			while (keys.hasNext()) {
+				String key = keys.next();
+				JsonBall value = container.getMetadata().get(key);
+				System.out.println(key + ":" + value);
+			}
+			assertNotNull(container.getUserMetadata());
+			Map<String, String> pContainerMetaDataOut = container
+					.getUserMetadata();
+			keys = pContainerMetaDataIn.keySet().iterator();
+			while (keys.hasNext()) {
+				String key = keys.next();
+				assertEquals(pContainerMetaDataOut.containsKey(key), true);
+				assertEquals(pContainerMetaDataOut.get(key),
+						pContainerMetaDataIn.get(key));
+			}
+			System.out.println("UserMetaData: " + container.getUserMetadata());
+			assertNotNull(container.getSystemMetadata());
+			System.out.println("SystemMetaData: "
+					+ container.getSystemMetadata());
+			assertNotNull(container.getACLMetadata());
+			assertEquals(container.getACLMetadata().size(),3);
+			List<Map<String, String>> aclMetadataOut = container
+					.getACLMetadata();
+			System.out.println("ACLMetaData: ");
+			for (Map<String, String> aclMap : aclMetadataOut) {
+				System.out.println(aclMap);
+			}
+			container = api.getContainer("/");
+			System.out.println("root container: " + container);
+			assertEquals(
+					container.getChildren().contains(pContainerName),
+					true);
+			System.out.println("adding containers to container");
+			String firstParentURI = api.getContainer(pContainerName).getObjectName();
+			for(int i=0;i<10;i++) {
+//				container = api.createContainer(firstParentURI+"childcontainer"+i+"/");
+				container = api.createContainer(pContainerName+"childcontainer"+i+"/");
+				assertNotNull(container);
+				System.out.println(container);
+				assertEquals(container.getParentURI(),pContainerName);
+				assertEquals(container.getObjectName(),"childcontainer"+i+"/");
+				container = api.createContainer(container.getParentURI()+container.getObjectName()+"grandchild/");
+				assertEquals(container.getParentURI(),pContainerName+"childcontainer"+i+"/");
+				assertEquals(container.getObjectName(),"grandchild/");				
+				System.out.println(container);				
+			}
+			container = api.getContainer(pContainerName);
+			assertNotNull(container);
+			assertNotNull(container.getChildren());
+			assertEquals(container.getChildren().size(), 10);	
+			
+		} finally {
+			Logger.getAnonymousLogger().info(
+					"deleteContainer: " + pContainerName);
+			api.deleteContainer(pContainerName);
+			container = api.getContainer("/");
+			System.out.println("root container: " + container);
+			assertEquals(
+					container.getChildren().contains(pContainerName),
+					false);
+		}
+
+	}
+	
+	@Test
+	public void testGetContainer() throws Exception {
+		String pContainerName = "MyContainer" + System.currentTimeMillis() + "/";
 		Map<String, String> pContainerMetaDataIn = new HashMap<String, String>();
 		Iterator<String> keys;
 		pContainerMetaDataIn.put("containerkey1", "value1");
 		pContainerMetaDataIn.put("containerkey2", "value2");
 		pContainerMetaDataIn.put("containerkey3", "value3");
 		CreateContainerOptions pCreateContainerOptions = CreateContainerOptions.Builder
-				.withMetadata(pContainerMetaDataIn);
+				.metadata(pContainerMetaDataIn);
 		ContainerApi api = cdmiContext.getApi().getContainerApi();
+
 		Logger.getAnonymousLogger().info("createContainer: " + pContainerName);
+
 		Container container = api.createContainer(pContainerName,
 				pCreateContainerOptions);
 		assertNotNull(container);
-		System.out.println(container);
-		Logger.getAnonymousLogger().info("getContainer: " + pContainerName);
-		container = api.getContainer(pContainerName);
-		assertNotNull(container);
-		System.out.println(container);
-		assertEquals(container.getObjectType(), ObjectTypes.CONTAINER);
-		assertNotNull(container.getObjectID());
-		assertNotNull(container.getObjectName());
-		assertEquals(container.getObjectName(), pContainerName + "/");
-		assertEquals(container.getParentURI(), "/");
-		assertNotNull(container.getChildren());
-		assertEquals(container.getChildren().isEmpty(), true);
-		System.out.println("Children: " + container.getChildren());
-		assertNotNull(container.getMetadata());
-		System.out.println("Raw metadata: " + container.getMetadata());
-		keys = container.getMetadata().keySet().iterator();
-		while (keys.hasNext()) {
-			String key = keys.next();
-			JsonBall value = container.getMetadata().get(key);
-			System.out.println(key + ":" + value);
+		try {
+			System.out.println(container);
+			Logger.getAnonymousLogger().info("getContainer: " + pContainerName);
+			container = api.getContainer(pContainerName);
+			assertNotNull(container);
+			System.out.println(container);
+			assertEquals(container.getObjectType(), ObjectTypes.CONTAINER);
+			assertNotNull(container.getObjectID());
+			assertNotNull(container.getObjectName());
+			assertEquals(container.getObjectName(), pContainerName);
+			assertEquals(container.getParentURI(), "/");
+			assertNotNull(container.getChildren());
+			assertEquals(container.getChildren().isEmpty(), true);
+			System.out.println("Children: " + container.getChildren());
+			assertNotNull(container.getMetadata());
+			System.out.println("Raw metadata: " + container.getMetadata());
+			keys = container.getMetadata().keySet().iterator();
+			while (keys.hasNext()) {
+				String key = keys.next();
+				JsonBall value = container.getMetadata().get(key);
+				System.out.println(key + ":" + value);
+			}
+			assertNotNull(container.getUserMetadata());
+			Map<String, String> pContainerMetaDataOut = container
+					.getUserMetadata();
+			keys = pContainerMetaDataIn.keySet().iterator();
+			while (keys.hasNext()) {
+				String key = keys.next();
+				assertEquals(pContainerMetaDataOut.containsKey(key), true);
+				assertEquals(pContainerMetaDataOut.get(key),
+						pContainerMetaDataIn.get(key));
+			}
+			System.out.println("UserMetaData: " + container.getUserMetadata());
+			assertNotNull(container.getSystemMetadata());
+			System.out.println("SystemMetaData: "
+					+ container.getSystemMetadata());
+			assertNotNull(container.getACLMetadata());
+			List<Map<String, String>> aclMetadataOut = container
+					.getACLMetadata();
+			System.out.println("ACLMetaData: ");
+			for (Map<String, String> aclMap : aclMetadataOut) {
+				System.out.println(aclMap);
+			}
+			container = api.getContainer("/");
+			System.out.println("root container: " + container);
+			assertEquals(
+					container.getChildren().contains(pContainerName),
+					true);
+			container = api.getContainer(pContainerName,ContainerQueryParams.Builder.field("parentURI"));
+			assertNotNull(container);
+			assertEquals(container.getParentURI(),"/");
+			System.out.println(container);
+			
+			container = api.getContainer(pContainerName,ContainerQueryParams.Builder.field("parentURI").field("objectName"));
+			assertNotNull(container);
+			assertEquals(container.getParentURI(),"/");
+			assertEquals(container.getObjectName(),pContainerName);			
+
+			container = api.getContainer(pContainerName,ContainerQueryParams.Builder.metadata());
+			assertNotNull(container);
+			pContainerMetaDataOut = container.getUserMetadata();
+			keys = pContainerMetaDataIn.keySet().iterator();
+			while (keys.hasNext()) {
+				String key = keys.next();
+				assertEquals(pContainerMetaDataOut.containsKey(key), true);
+				assertEquals(pContainerMetaDataOut.get(key),
+						pContainerMetaDataIn.get(key));
+			}
+			System.out.println(container);
+			
+			System.out.println("GetContainerOptions.Builder.metadata(cdmi_acl)");
+			container = api.getContainer(pContainerName,ContainerQueryParams.Builder.metadata("cdmi_acl"));
+			assertNotNull(container);
+			System.out.println(container);			
+			assertNotNull(container.getACLMetadata());
+			assertEquals(container.getACLMetadata().size(),3);
+
+			
+			System.out.println("adding containers to container");
+			String firstParentURI = api.getContainer(pContainerName).getObjectName();
+			for(int i=0;i<10;i++) {
+				container = api.createContainer(firstParentURI+"childcontainer"+i+"/");
+				assertNotNull(container);
+				assertEquals(container.getParentURI(),pContainerName);
+				assertEquals(container.getObjectName(),"childcontainer"+i+"/");
+				container = api.createContainer(container.getParentURI()+container.getObjectName()+"grandchild/",pCreateContainerOptions);
+				assertEquals(container.getParentURI(),pContainerName+"childcontainer"+i+"/");
+				assertEquals(container.getObjectName(),"grandchild"+"/");
+				container = api.getContainer(container.getParentURI(),ContainerQueryParams.Builder.children());
+				assertEquals(container.getChildren().contains("grandchild"+"/"),true);
+			}
+			container = api.getContainer(pContainerName,ContainerQueryParams.Builder.children());
+			assertNotNull(container);
+			assertNotNull(container.getChildren());
+			assertEquals(container.getChildren().size(), 10);
+			container = api.getContainer(pContainerName,ContainerQueryParams.Builder.children(0,3));
+			assertNotNull(container);
+			assertNotNull(container.getChildren());
+			assertEquals(container.getChildren().size(), 4);
+			
+			container = api.getContainer(pContainerName,ContainerQueryParams.Builder.field("parentURI").field("objectName").children().metadata());
+			assertNotNull(container);
+			assertNotNull(container.getChildren());
+			assertEquals(container.getChildren().size(), 10);
+			assertEquals(container.getParentURI(),"/");
+			assertEquals(container.getObjectName(),pContainerName);	
+			assertEquals(container.getParentURI(),"/");
+			assertEquals(container.getACLMetadata().size(),3);
+			for(String childName: container.getChildren()){
+				api.deleteContainer(container.getObjectName()+ childName);				
+			}
+			assertEquals(api.getContainer(pContainerName,ContainerQueryParams.Builder.children()).getChildren().isEmpty(),true);
+			
+		} finally {
+			Logger.getAnonymousLogger().info(
+					"deleteContainer: " + pContainerName);
+			api.deleteContainer(pContainerName);
+			container = api.getContainer("/");
+			System.out.println("root container: " + container);
+			assertEquals(
+					container.getChildren().contains(pContainerName),
+					false);
 		}
-		assertNotNull(container.getUserMetadata());
-		Map<String, String> pContainerMetaDataOut = container.getUserMetadata();
-		keys = pContainerMetaDataIn.keySet().iterator();
-		while (keys.hasNext()) {
-			String key = keys.next();
-			assertEquals(pContainerMetaDataOut.containsKey(key), true);
-			assertEquals(pContainerMetaDataOut.get(key),
-					pContainerMetaDataIn.get(key));
-		}
-		System.out.println("UserMetaData: " + container.getUserMetadata());
-		assertNotNull(container.getSystemMetadata());
-		System.out.println("SystemMetaData: " + container.getSystemMetadata());
-		assertNotNull(container.getACLMetadata());
-		List<Map<String, String>> aclMetadataOut = container.getACLMetadata();
-		System.out.println("ACLMetaData: ");
-		for (Map<String, String> aclMap : aclMetadataOut) {
-			System.out.println(aclMap);
-		}
-		container = api.getContainer("/");
-		System.out.println("root container: " + container);
-		assertEquals(container.getChildren().contains(pContainerName + "/"),
-				true);
-		Logger.getAnonymousLogger().info("deleteContainer: " + pContainerName);
-		api.deleteContainer(pContainerName);
-		container = api.getContainer("/");
-		System.out.println("root container: " + container);
-		assertEquals(container.getChildren().contains(pContainerName + "/"),
-				false);
 
 	}
 
+
 }
diff --git a/labs/cdmi/src/test/java/org/jclouds/snia/cdmi/v1/features/DataApiLiveTest.java b/labs/cdmi/src/test/java/org/jclouds/snia/cdmi/v1/features/DataApiLiveTest.java
index 7a0c295..91200d7 100644
--- a/labs/cdmi/src/test/java/org/jclouds/snia/cdmi/v1/features/DataApiLiveTest.java
+++ b/labs/cdmi/src/test/java/org/jclouds/snia/cdmi/v1/features/DataApiLiveTest.java
@@ -37,8 +37,8 @@
 import org.jclouds.snia.cdmi.v1.domain.DataObject;
 import org.jclouds.snia.cdmi.v1.internal.BaseCDMIApiLiveTest;
 import org.jclouds.snia.cdmi.v1.options.CreateContainerOptions;
-import org.jclouds.snia.cdmi.v1.options.CreateDataObjectNonCDMIOptions;
 import org.jclouds.snia.cdmi.v1.options.CreateDataObjectOptions;
+import org.jclouds.snia.cdmi.v1.queryparams.DataObjectQueryParams;
 import org.testng.annotations.Test;
 
 import com.google.common.base.Charsets;
@@ -53,13 +53,18 @@
 	@Test
 	public void testCreateDataObjects() throws Exception {
 
-		String containerName = "MyContainer" + System.currentTimeMillis();
-		String dataObjectNameIn = "dataobject1.txt";
+		String containerName = "MyContainer" + System.currentTimeMillis() + "/";
+		String dataObjectNameIn = "dataobject08121.txt";
 		File tmpFileIn = new File("temp.txt");
 		String value;
 		InputStream is;
 		File tmpFileOut;
+		File inFile;
 		Files.touch(tmpFileIn);
+		ByteArrayOutputStream bos = new ByteArrayOutputStream();
+		DataOutputStream out = new DataOutputStream(bos);
+		byte[] bytes;
+		
 		CreateDataObjectOptions pCreateDataObjectOptions;
 		DataObject dataObject;
 		Iterator<String> keys;
@@ -71,7 +76,7 @@
 		pDataObjectMetaDataIn.put("dataObjectkey3", "value3");
 
 		CreateContainerOptions pCreateContainerOptions = CreateContainerOptions.Builder
-				.withMetadata(pContainerMetaDataIn);
+				.metadata(pContainerMetaDataIn);
 		ContainerApi containerApi = cdmiContext.getApi()
 				.getContainerApi();
 		DataApi dataApi = cdmiContext.getApi().getDataApi();
@@ -85,35 +90,9 @@
 			assertNotNull(container);
 			assertNotNull(container.getChildren());
 			assertEquals(container.getChildren().isEmpty(), true);
-
-			// exercise create data object with none cdmi put
-			value = "Hello CDMI World1";
-			CreateDataObjectNonCDMIOptions pCreateDataObjectNoneCDMIOptions = CreateDataObjectNonCDMIOptions.Builder
-					.withStringPayload(value);
-			dataApi.createDataObjectNonCDMI(containerName, dataObjectNameIn,
-					pCreateDataObjectNoneCDMIOptions);
-			System.out.println(containerApi.getContainer(containerName));
-			dataObject = dataApi.getDataObject(containerName,
-					dataObjectNameIn);
-			assertNotNull(dataObject);
-			System.out.println(dataObject);
-			System.out.println("value: " + dataObject.getValueAsString());
-			assertEquals(dataObject.getValueAsString(), value);
-			assertEquals(dataObject.getUserMetadata().isEmpty(), true);
-			assertEquals(
-					Integer.parseInt(dataObject.getSystemMetadata().get(
-							"cdmi_size")), value.length());
-			assertEquals(dataObject.getObjectName(), dataObjectNameIn);
-			assertEquals(dataObject.getObjectType(), "application/cdmi-object");
-			assertEquals(dataObject.getParentURI(), "/" + containerName + "/");
-			assertEquals(containerApi.getContainer(containerName)
-					.getChildren().contains(dataObjectNameIn), true);
-			dataApi.deleteDataObject(containerName, dataObjectNameIn);
-			assertEquals(containerApi.getContainer(containerName)
-					.getChildren().contains(dataObjectNameIn), false);
-
+			
 			// exercise create data object with value mimetype and metadata
-			value = "Hello CDMI World2";
+			value = "Hello CDMI data object with value mimetype and metadata";
 			pCreateDataObjectOptions = CreateDataObjectOptions.Builder
 					.value(value).mimetype("text/plain")
 					.metadata(pDataObjectMetaDataIn);
@@ -141,9 +120,10 @@
 							"cdmi_size")), value.length());
 			assertEquals(dataObject.getObjectName(), dataObjectNameIn);
 			assertEquals(dataObject.getObjectType(), "application/cdmi-object");
-			assertEquals(dataObject.getParentURI(), "/" + containerName + "/");
+			assertEquals(dataObject.getParentURI(), "/" + containerName );
 			assertEquals(containerApi.getContainer(containerName)
 					.getChildren().contains(dataObjectNameIn), true);
+			
 			dataApi.deleteDataObject(containerName, dataObjectNameIn);
 			assertEquals(containerApi.getContainer(containerName)
 					.getChildren().contains(dataObjectNameIn), false);
@@ -177,7 +157,7 @@
 							"cdmi_size")), value.length());
 			assertEquals(dataObject.getObjectName(), dataObjectNameIn);
 			assertEquals(dataObject.getObjectType(), "application/cdmi-object");
-			assertEquals(dataObject.getParentURI(), "/" + containerName + "/");
+			assertEquals(dataObject.getParentURI(), "/" + containerName);
 			assertEquals(containerApi.getContainer(containerName)
 					.getChildren().contains(dataObjectNameIn), true);
 			dataApi.deleteDataObject(containerName, dataObjectNameIn);
@@ -202,13 +182,13 @@
 			assertEquals(dataObject.getValueAsString(), value);
 			dataObjectMetaDataOut = dataObject.getUserMetadata();
 			assertNotNull(dataObjectMetaDataOut);
-			assertEquals(true, dataObjectMetaDataOut.isEmpty());
+			assertEquals(dataObjectMetaDataOut.isEmpty(),true);
 			assertEquals(
 					Integer.parseInt(dataObject.getSystemMetadata().get(
 							"cdmi_size")), value.length());
 			assertEquals(dataObject.getObjectName(), dataObjectNameIn);
 			assertEquals(dataObject.getObjectType(), "application/cdmi-object");
-			assertEquals(dataObject.getParentURI(), "/" + containerName + "/");
+			assertEquals(dataObject.getParentURI(), "/" + containerName);
 			assertEquals(containerApi.getContainer(containerName)
 					.getChildren().contains(dataObjectNameIn), true);
 			dataApi.deleteDataObject(containerName, dataObjectNameIn);
@@ -237,7 +217,7 @@
 							"cdmi_size")), value.length());
 			assertEquals(dataObject.getObjectName(), dataObjectNameIn);
 			assertEquals(dataObject.getObjectType(), "application/cdmi-object");
-			assertEquals(dataObject.getParentURI(), "/" + containerName + "/");
+			assertEquals(dataObject.getParentURI(), "/" + containerName);
 			assertEquals(containerApi.getContainer(containerName)
 					.getChildren().contains(dataObjectNameIn), true);
 			dataApi.deleteDataObject(containerName, dataObjectNameIn);
@@ -259,13 +239,13 @@
 			assertEquals(dataObject.getValueAsString(), value);
 			dataObjectMetaDataOut = dataObject.getUserMetadata();
 			assertNotNull(dataObjectMetaDataOut);
-			assertEquals(true, dataObjectMetaDataOut.isEmpty());
+			assertEquals(dataObjectMetaDataOut.isEmpty(),true);
 			assertEquals(
 					Integer.parseInt(dataObject.getSystemMetadata().get(
 							"cdmi_size")), value.length());
 			assertEquals(dataObject.getObjectName(), dataObjectNameIn);
 			assertEquals(dataObject.getObjectType(), "application/cdmi-object");
-			assertEquals(dataObject.getParentURI(), "/" + containerName + "/");
+			assertEquals(dataObject.getParentURI(), "/" + containerName);
 			assertEquals(containerApi.getContainer(containerName)
 					.getChildren().contains(dataObjectNameIn), true);
 			dataApi.deleteDataObject(containerName, dataObjectNameIn);
@@ -284,11 +264,11 @@
 			assertNotNull(dataObject);
 			System.out.println(dataObject);
 			System.out.println("value: " + dataObject.getValueAsString());
-			assertEquals(dataObject.getMimetype(), "");
+			//assertEquals(dataObject.getMimetype(), "");
 			assertEquals(dataObject.getValueAsString(), "");
 			dataObjectMetaDataOut = dataObject.getUserMetadata();
 			assertNotNull(dataObjectMetaDataOut);
-			assertEquals(true, dataObjectMetaDataOut.isEmpty());
+			//assertEquals(dataObjectMetaDataOut.isEmpty(),true);
 
 			dataApi.deleteDataObject(containerName, dataObjectNameIn);
 
@@ -306,13 +286,13 @@
 			assertEquals(dataObject.getValueAsString(), "");
 			dataObjectMetaDataOut = dataObject.getUserMetadata();
 			assertNotNull(dataObjectMetaDataOut);
-			assertEquals(true, dataObjectMetaDataOut.isEmpty());
+			assertEquals(dataObjectMetaDataOut.isEmpty(),true);
 			assertEquals(
 					Integer.parseInt(dataObject.getSystemMetadata().get(
 							"cdmi_size")), value.length());
 			assertEquals(dataObject.getObjectName(), dataObjectNameIn);
 			assertEquals(dataObject.getObjectType(), "application/cdmi-object");
-			assertEquals(dataObject.getParentURI(), "/" + containerName + "/");
+			assertEquals(dataObject.getParentURI(), "/" + containerName);
 			assertEquals(containerApi.getContainer(containerName)
 					.getChildren().contains(dataObjectNameIn), true);
 			dataApi.deleteDataObject(containerName, dataObjectNameIn);
@@ -321,11 +301,11 @@
 
 			// exercise create data object with byte array
 			value = "Hello CDMI World 7";
-			ByteArrayOutputStream bos = new ByteArrayOutputStream();
-			DataOutputStream out = new DataOutputStream(bos);
 			out.writeUTF(value);
 			out.close();
-			byte[] bytes = bos.toByteArray();
+			bytes = bos.toByteArray();
+			// String.getBytes causes an exception CreateDataObjectOptions need to investigate byte arrays
+			//bytes = value.getBytes("UTF-8");  
 			pCreateDataObjectOptions = CreateDataObjectOptions.Builder
 					.value(bytes);
 			dataObject = dataApi.createDataObject(containerName,
@@ -343,7 +323,7 @@
 							"cdmi_size")), value.length());
 			assertEquals(dataObject.getObjectName(), dataObjectNameIn);
 			assertEquals(dataObject.getObjectType(), "application/cdmi-object");
-			assertEquals(dataObject.getParentURI(), "/" + containerName + "/");
+			assertEquals(dataObject.getParentURI(), "/" + containerName);
 			assertEquals(containerApi.getContainer(containerName)
 					.getChildren().contains(dataObjectNameIn), true);
 			dataApi.deleteDataObject(containerName, dataObjectNameIn);
@@ -351,7 +331,7 @@
 					.getChildren().contains(dataObjectNameIn), false);
 
 			// exercise create data object with an existing file
-			File inFile = new File(System.getProperty("user.dir")
+			inFile = new File(System.getProperty("user.dir")
 					+ "/src/test/resources/container.json");
 			assertEquals(true, inFile.isFile());
 			pCreateDataObjectOptions = CreateDataObjectOptions.Builder
@@ -373,7 +353,7 @@
 					Files.toString(inFile, Charsets.UTF_8).length());
 			assertEquals(dataObject.getObjectName(), dataObjectNameIn);
 			assertEquals(dataObject.getObjectType(), "application/cdmi-object");
-			assertEquals(dataObject.getParentURI(), "/" + containerName + "/");
+			assertEquals(dataObject.getParentURI(), "/" + containerName);
 			assertEquals(containerApi.getContainer(containerName)
 					.getChildren().contains(dataObjectNameIn), true);
 			dataApi.deleteDataObject(containerName, dataObjectNameIn);
@@ -404,7 +384,7 @@
 							"cdmi_size")), value.length());
 			assertEquals(dataObject.getObjectName(), dataObjectNameIn);
 			assertEquals(dataObject.getObjectType(), "application/cdmi-object");
-			assertEquals(dataObject.getParentURI(), "/" + containerName + "/");
+			assertEquals(dataObject.getParentURI(), "/" + containerName);
 			assertEquals(containerApi.getContainer(containerName)
 					.getChildren().contains(dataObjectNameIn), true);
 			dataApi.deleteDataObject(containerName, dataObjectNameIn);
@@ -434,7 +414,7 @@
 							"cdmi_size")), value.length());
 			assertEquals(dataObject.getObjectName(), dataObjectNameIn);
 			assertEquals(dataObject.getObjectType(), "application/cdmi-object");
-			assertEquals(dataObject.getParentURI(), "/" + containerName + "/");
+			assertEquals(dataObject.getParentURI(), "/" + containerName);
 			assertEquals(containerApi.getContainer(containerName)
 					.getChildren().contains(dataObjectNameIn), true);
 			dataApi.deleteDataObject(containerName, dataObjectNameIn);
@@ -464,7 +444,7 @@
 							"cdmi_size")), value.length());
 			assertEquals(dataObject.getObjectName(), dataObjectNameIn);
 			assertEquals(dataObject.getObjectType(), "application/cdmi-object");
-			assertEquals(dataObject.getParentURI(), "/" + containerName + "/");
+			assertEquals(dataObject.getParentURI(), "/" + containerName);
 			assertEquals(containerApi.getContainer(containerName)
 					.getChildren().contains(dataObjectNameIn), true);
 			dataApi.deleteDataObject(containerName, dataObjectNameIn);
@@ -497,7 +477,7 @@
 					Files.toString(tmpFileIn, Charsets.UTF_8).length());
 			assertEquals(dataObject.getObjectName(), dataObjectNameIn);
 			assertEquals(dataObject.getObjectType(), "application/cdmi-object");
-			assertEquals(dataObject.getParentURI(), "/" + containerName + "/");
+			assertEquals(dataObject.getParentURI(), "/" + containerName);
 			assertEquals(containerApi.getContainer(containerName)
 					.getChildren().contains(dataObjectNameIn), true);
 			dataApi.deleteDataObject(containerName, dataObjectNameIn);
@@ -530,7 +510,7 @@
 					Files.toString(tmpFileIn, Charsets.UTF_8).length());
 			assertEquals(dataObject.getObjectName(), dataObjectNameIn);
 			assertEquals(dataObject.getObjectType(), "application/cdmi-object");
-			assertEquals(dataObject.getParentURI(), "/" + containerName + "/");
+			assertEquals(dataObject.getParentURI(), "/" + containerName);
 			assertEquals(containerApi.getContainer(containerName)
 					.getChildren().contains(dataObjectNameIn), true);
 			dataApi.deleteDataObject(containerName, dataObjectNameIn);
@@ -563,7 +543,7 @@
 					Files.toString(tmpFileIn, Charsets.ISO_8859_1).length());
 			assertEquals(dataObject.getObjectName(), dataObjectNameIn);
 			assertEquals(dataObject.getObjectType(), "application/cdmi-object");
-			assertEquals(dataObject.getParentURI(), "/" + containerName + "/");
+			assertEquals(dataObject.getParentURI(), "/" + containerName);
 			assertEquals(containerApi.getContainer(containerName)
 					.getChildren().contains(dataObjectNameIn), true);
 			dataApi.deleteDataObject(containerName, dataObjectNameIn);
@@ -591,13 +571,12 @@
 							"cdmi_size")), value.length());
 			assertEquals(dataObject.getObjectName(), dataObjectNameIn);
 			assertEquals(dataObject.getObjectType(), "application/cdmi-object");
-			assertEquals(dataObject.getParentURI(), "/" + containerName + "/");
+			assertEquals(dataObject.getParentURI(), "/" + containerName);
 			assertEquals(containerApi.getContainer(containerName)
 					.getChildren().contains(dataObjectNameIn), true);
 			dataApi.deleteDataObject(containerName, dataObjectNameIn);
 			assertEquals(containerApi.getContainer(containerName)
 					.getChildren().contains(dataObjectNameIn), false);
-
 		} finally {
 			tmpFileIn.delete();
 			containerApi.deleteContainer(containerName);
@@ -605,5 +584,152 @@
 		}
 
 	}
+	
+	@Test
+	public void testGetDataObjects() throws Exception {
+
+		String containerName = "MyContainer" + System.currentTimeMillis() + "/";
+		String dataObjectNameIn = "dataobject08121.txt";
+		File tmpFileIn = new File("temp.txt");
+		String value;
+		Files.touch(tmpFileIn);
+		
+		CreateDataObjectOptions pCreateDataObjectOptions;
+		DataObject dataObject;
+		Iterator<String> keys;
+		Map<String, String> dataObjectMetaDataOut;
+		Map<String, String> pContainerMetaDataIn = new HashMap<String, String>();
+		Map<String, String> pDataObjectMetaDataIn = new LinkedHashMap<String, String>();
+		pDataObjectMetaDataIn.put("dataObjectkey1", "value1");
+		pDataObjectMetaDataIn.put("dataObjectkey2", "value2");
+		pDataObjectMetaDataIn.put("dataObjectkey3", "value3");
+
+		CreateContainerOptions pCreateContainerOptions = CreateContainerOptions.Builder
+				.metadata(pContainerMetaDataIn);
+		ContainerApi containerApi = cdmiContext.getApi()
+				.getContainerApi();
+		DataApi dataApi = cdmiContext.getApi().getDataApi();
+		Logger.getAnonymousLogger().info("createContainer: " + containerName);
+		Container container = containerApi.createContainer(containerName,
+				pCreateContainerOptions);
+		try {
+			assertNotNull(container);
+			System.out.println(container);
+			container = containerApi.getContainer(containerName);
+			assertNotNull(container);
+			assertNotNull(container.getChildren());
+			assertEquals(container.getChildren().isEmpty(), true);
+			
+			// exercise create data object with value mimetype and metadata
+			value = "Hello CDMI data object with value mimetype and metadata";
+			pCreateDataObjectOptions = CreateDataObjectOptions.Builder
+					.value(value).mimetype("text/plain")
+					.metadata(pDataObjectMetaDataIn);
+			dataObject = dataApi.createDataObject(containerName,
+					dataObjectNameIn, pCreateDataObjectOptions);
+			assertNotNull(dataObject);
+			dataObject = dataApi.getDataObject(containerName,
+					dataObjectNameIn);
+			assertNotNull(dataObject);
+			System.out.println(dataObject);
+			System.out.println("value: " + dataObject.getValueAsString());
+			assertEquals(dataObject.getMimetype(), "text/plain");
+			assertEquals(dataObject.getValueAsString(), value);
+			dataObjectMetaDataOut = dataObject.getUserMetadata();
+			assertNotNull(dataObjectMetaDataOut);
+			keys = pDataObjectMetaDataIn.keySet().iterator();
+			while (keys.hasNext()) {
+				String key = keys.next();
+				assertEquals(dataObjectMetaDataOut.containsKey(key), true);
+				assertEquals(dataObjectMetaDataOut.get(key),
+						pDataObjectMetaDataIn.get(key));
+			}
+			assertEquals(
+					Integer.parseInt(dataObject.getSystemMetadata().get(
+							"cdmi_size")), value.length());
+			assertEquals(dataObject.getObjectName(), dataObjectNameIn);
+			assertEquals(dataObject.getObjectType(), "application/cdmi-object");
+			assertEquals(dataObject.getParentURI(), "/" + containerName);
+			assertEquals(containerApi.getContainer(containerName)
+					.getChildren().contains(dataObjectNameIn), true);
+			
+			dataObject = dataApi.getDataObject(containerName,
+					dataObjectNameIn,DataObjectQueryParams.Builder.field("parentURI"));
+			assertNotNull(dataObject);
+			System.out.println(dataObject);
+			assertEquals(dataObject.getParentURI(),container.getParentURI()+container.getObjectName());
+			
+			dataObject = dataApi.getDataObject(containerName,
+					dataObjectNameIn,DataObjectQueryParams.Builder.field("parentURI").field("objectName"));
+			assertNotNull(dataObject);
+			System.out.println(dataObject);			
+			assertEquals(dataObject.getParentURI(),container.getParentURI()+container.getObjectName());
+			assertEquals(dataObject.getObjectName(),dataObjectNameIn);
+
+			dataObject = dataApi.getDataObject(containerName,
+					dataObjectNameIn,DataObjectQueryParams.Builder.field("parentURI").field("objectName").field("mimetype"));
+			assertNotNull(dataObject);
+			System.out.println(dataObject);			
+			assertEquals(dataObject.getParentURI(),container.getParentURI()+container.getObjectName());
+			assertEquals(dataObject.getObjectName(),dataObjectNameIn);
+			assertEquals(dataObject.getMimetype(),"text/plain");
+
+			dataObject = dataApi.getDataObject(containerName,
+					dataObjectNameIn,DataObjectQueryParams.Builder.field("parentURI").field("objectName").field("mimetype").metadata());
+			assertNotNull(dataObject);
+			System.out.println(dataObject);			
+			assertEquals(dataObject.getParentURI(),container.getParentURI()+container.getObjectName());
+			assertEquals(dataObject.getObjectName(),dataObjectNameIn);
+			assertEquals(dataObject.getMimetype(),"text/plain");			
+			dataObjectMetaDataOut = dataObject.getUserMetadata();
+			assertNotNull(dataObjectMetaDataOut);
+			keys = pDataObjectMetaDataIn.keySet().iterator();
+			while (keys.hasNext()) {
+				String key = keys.next();
+				assertEquals(dataObjectMetaDataOut.containsKey(key), true);
+				assertEquals(dataObjectMetaDataOut.get(key),
+						pDataObjectMetaDataIn.get(key));
+			}
+			assertEquals(
+					Integer.parseInt(dataObject.getSystemMetadata().get(
+							"cdmi_size")), value.length());
+			
+			dataObject = dataApi.getDataObject(containerName,
+					dataObjectNameIn,DataObjectQueryParams.Builder.metadata("cdmi_size"));
+			assertNotNull(dataObject);
+			System.out.println(dataObject);			
+			assertEquals(
+					Integer.parseInt(dataObject.getSystemMetadata().get(
+							"cdmi_size")), value.length());
+
+			dataObject = dataApi.getDataObject(containerName,
+					dataObjectNameIn,DataObjectQueryParams.Builder.field("mimetype").value());
+			assertNotNull(dataObject);
+			System.out.println(dataObject);
+			System.out.println(dataObject.getValueAsString());
+			assertEquals(dataObject.getMimetype(),"text/plain");
+			assertEquals(dataObject.getValueAsString(),value);
+			
+			dataObject = dataApi.getDataObject(containerName,
+					dataObjectNameIn,DataObjectQueryParams.Builder.field("mimetype").value(0,3));
+			assertNotNull(dataObject);
+			System.out.println(dataObject);
+			System.out.println(dataObject.getValueAsString());
+			assertEquals(dataObject.getMimetype(),"text/plain");
+			//value is SGVsbA==. This needs investigating to determine if this
+			//is problem with CDMI server or the jcloud client or must understanding of spec
+
+
+			dataApi.deleteDataObject(containerName, dataObjectNameIn);
+			assertEquals(containerApi.getContainer(containerName)
+					.getChildren().contains(dataObjectNameIn), false);
+		} finally {
+			tmpFileIn.delete();
+			containerApi.deleteContainer(containerName);
+
+		}
+
+	}
+
 
 }
diff --git a/labs/cdmi/src/test/java/org/jclouds/snia/cdmi/v1/features/DataNonCDMIContentTypeApiLiveTest.java b/labs/cdmi/src/test/java/org/jclouds/snia/cdmi/v1/features/DataNonCDMIContentTypeApiLiveTest.java
new file mode 100644
index 0000000..649b32c
--- /dev/null
+++ b/labs/cdmi/src/test/java/org/jclouds/snia/cdmi/v1/features/DataNonCDMIContentTypeApiLiveTest.java
@@ -0,0 +1,421 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.snia.cdmi.v1.features;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.logging.Logger;
+import org.jclouds.io.Payload;
+import org.jclouds.io.payloads.BaseMutableContentMetadata;
+import org.jclouds.io.payloads.ByteArrayPayload;
+import org.jclouds.io.payloads.FilePayload;
+import org.jclouds.io.payloads.InputStreamPayload;
+import org.jclouds.io.payloads.StringPayload;
+import org.jclouds.snia.cdmi.v1.domain.Container;
+import org.jclouds.snia.cdmi.v1.domain.DataObject;
+import org.jclouds.snia.cdmi.v1.internal.BaseCDMIApiLiveTest;
+import org.jclouds.snia.cdmi.v1.options.CreateContainerOptions;
+import org.jclouds.snia.cdmi.v1.queryparams.DataObjectQueryParams;
+import org.testng.annotations.Test;
+
+import com.google.common.base.Charsets;
+import com.google.common.io.ByteStreams;
+import com.google.common.io.CharStreams;
+import com.google.common.io.Files;
+import com.google.common.net.MediaType;
+
+/**
+ * @author Kenneth Nagin
+ */
+@Test(groups = "live", testName = "DataNonCDMIContentTypeApiLiveTest")
+public class DataNonCDMIContentTypeApiLiveTest extends BaseCDMIApiLiveTest {
+	@Test
+	public void testCreateDataObjectsNonCDMI() throws Exception {
+
+		String containerName = "MyContainer" + System.currentTimeMillis() + "/";
+		String dataObjectNameIn = "dataobject.txt";
+		File tmpFileIn = new File("temp.txt");
+		String value;
+		InputStream is;
+		File tmpFileOut;
+		File inFile;
+		Files.touch(tmpFileIn);
+		byte[] bytes;
+		DataObject dataObject;
+		Map<String, String> pContainerMetaDataIn = new HashMap<String, String>();
+		Map<String, String> pDataObjectMetaDataIn = new LinkedHashMap<String, String>();
+		pDataObjectMetaDataIn.put("dataObjectkey1", "value1");
+		pDataObjectMetaDataIn.put("dataObjectkey2", "value2");
+		pDataObjectMetaDataIn.put("dataObjectkey3", "value3");
+		
+		Payload payloadIn;
+		Payload payloadOut;
+		FileOutputStream fos;
+		
+
+		CreateContainerOptions pCreateContainerOptions = CreateContainerOptions.Builder
+				.metadata(pContainerMetaDataIn);
+		ContainerApi containerApi = cdmiContext.getApi()
+				.getContainerApi();
+		DataApi dataApi = cdmiContext.getApi().getDataApi();
+		DataNonCDMIContentTypeApi dataNonCDMIContentTypeApi = cdmiContext.getApi().getDataNonCDMIContentTypeApi();
+		Logger.getAnonymousLogger().info("createContainer: " + containerName);
+		Container container = containerApi.createContainer(containerName,
+				pCreateContainerOptions);
+		try {
+			
+			assertNotNull(container);
+			System.out.println(container);
+			container = containerApi.getContainer(containerName);
+			assertNotNull(container);
+			assertNotNull(container.getChildren());
+			assertEquals(container.getChildren().isEmpty(), true);
+			
+			// exercise create data object with none cdmi put with payload string.
+			value = "Hello CDMI World non-cdmi String";
+			dataNonCDMIContentTypeApi.createDataObject(containerName, dataObjectNameIn,
+					value);
+			payloadOut = dataNonCDMIContentTypeApi.getDataObjectValue(containerName, dataObjectNameIn);
+			assertNotNull(payloadOut);
+			assertEquals(CharStreams.toString(new InputStreamReader(payloadOut.getInput(), "UTF-8")),value);
+			
+			payloadIn = new StringPayload(value);
+			payloadIn.setContentMetadata(BaseMutableContentMetadata.fromContentMetadata(payloadIn.getContentMetadata().toBuilder()
+					.contentType(MediaType.PLAIN_TEXT_UTF_8.toString())
+					.build()));
+			dataNonCDMIContentTypeApi.createDataObject(containerName, dataObjectNameIn,
+					payloadIn);
+
+			payloadOut = dataNonCDMIContentTypeApi.getDataObjectValue(containerName, dataObjectNameIn);
+			assertNotNull(payloadOut);
+			assertEquals(CharStreams.toString(new InputStreamReader(payloadOut.getInput(), "UTF-8")),value);
+			
+			dataObject = dataNonCDMIContentTypeApi.getDataObject(containerName, dataObjectNameIn, 
+					DataObjectQueryParams.Builder.field("parentURI"));
+			assertNotNull(dataObject);
+			System.out.println(dataObject);			
+			assertEquals(dataObject.getParentURI(), "/" + containerName);
+			dataObject = dataNonCDMIContentTypeApi.getDataObject(containerName, dataObjectNameIn, 
+					DataObjectQueryParams.Builder.metadata()
+					.field("parentURI")
+					.field("objectName")
+					.field("objectType")
+					.field("mimetype"));
+			assertEquals(
+					Integer.parseInt(dataObject.getSystemMetadata().get(
+							"cdmi_size")), value.length());
+			assertEquals(dataObject.getObjectName(), dataObjectNameIn);
+			assertEquals(dataObject.getObjectType(), "application/cdmi-object");
+			assertEquals(dataObject.getParentURI(), "/" + containerName);
+			assertEquals(dataObject.getMimetype(),MediaType.PLAIN_TEXT_UTF_8.toString());
+			
+
+			
+			dataNonCDMIContentTypeApi.deleteDataObject(containerName, dataObjectNameIn);
+			assertEquals(containerApi.getContainer(containerName)
+					.getChildren().contains(dataObjectNameIn), false);
+
+			// exercise create data object with none cdmi put with payload byte array.
+			value = "Hello CDMI World non-cdmi byte array";
+			bytes = value.getBytes("UTF-8");
+			payloadIn = new ByteArrayPayload(bytes);
+			payloadIn.setContentMetadata(BaseMutableContentMetadata.fromContentMetadata(payloadIn.getContentMetadata().toBuilder()
+					.contentType(MediaType.PLAIN_TEXT_UTF_8.toString())
+					.build()));
+			dataNonCDMIContentTypeApi.createDataObject(containerName, dataObjectNameIn,
+					payloadIn);
+			System.out.println(containerApi.getContainer(containerName));
+			dataObject = dataApi.getDataObject(containerName,
+					dataObjectNameIn);
+			assertNotNull(dataObject);
+			System.out.println(dataObject);
+			System.out.println("value: " + dataObject.getValueAsString());
+			assertEquals(dataObject.getValueAsString(), value);
+			assertEquals(new String(dataObject.getValueAsByteArray()), value);
+			assertEquals(dataObject.getUserMetadata().isEmpty(), true);
+			assertEquals(
+					Integer.parseInt(dataObject.getSystemMetadata().get(
+							"cdmi_size")), value.length());
+			assertEquals(dataObject.getObjectName(), dataObjectNameIn);
+			assertEquals(dataObject.getObjectType(), "application/cdmi-object");
+			assertEquals(dataObject.getParentURI(), "/" + containerName);
+			assertEquals(containerApi.getContainer(containerName)
+					.getChildren().contains(dataObjectNameIn), true);
+			payloadOut = dataNonCDMIContentTypeApi.getDataObjectValue(containerName, dataObjectNameIn);
+			assertNotNull(payloadOut);
+			assertEquals(CharStreams.toString(new InputStreamReader(payloadOut.getInput(), "UTF-8")),value);
+
+			
+			
+			dataNonCDMIContentTypeApi.deleteDataObject(containerName, dataObjectNameIn);
+			assertEquals(containerApi.getContainer(containerName)
+					.getChildren().contains(dataObjectNameIn), false);
+			
+			
+			
+
+			// exercise create data object with none cdmi put with payload file.
+			value = "Hello CDMI World non-cdmi File";
+			Files.write(value, tmpFileIn, Charsets.UTF_8);
+			payloadIn = new FilePayload(tmpFileIn);
+			payloadIn.setContentMetadata(BaseMutableContentMetadata.fromContentMetadata(payloadIn.getContentMetadata().toBuilder()
+					.contentType(MediaType.PLAIN_TEXT_UTF_8.toString())
+					.build()));
+			
+			dataNonCDMIContentTypeApi.createDataObject(containerName, dataObjectNameIn,
+					payloadIn);
+			System.out.println(containerApi.getContainer(containerName));
+			dataObject = dataApi.getDataObject(containerName,
+					dataObjectNameIn);
+			assertNotNull(dataObject);
+			System.out.println(dataObject);
+			System.out.println("value: " + dataObject.getValueAsString());
+			assertEquals(dataObject.getValueAsString(), value);
+			tmpFileOut = dataObject.getValueAsFile(Files.createTempDir());
+			assertEquals(true, Files.equal(tmpFileOut, tmpFileIn));
+			tmpFileOut.delete();
+			assertEquals(dataObject.getUserMetadata().isEmpty(), true);
+			System.out.println("My Metadata: "+dataObject.getUserMetadata());
+			assertEquals(
+					Integer.parseInt(dataObject.getSystemMetadata().get(
+							"cdmi_size")), value.length());
+			assertEquals(dataObject.getObjectName(), dataObjectNameIn);
+			assertEquals(dataObject.getObjectType(), "application/cdmi-object");
+			assertEquals(dataObject.getParentURI(), "/" + containerName);
+			assertEquals(containerApi.getContainer(containerName)
+					.getChildren().contains(dataObjectNameIn), true);
+			
+			payloadOut = dataNonCDMIContentTypeApi.getDataObjectValue(containerName, dataObjectNameIn);
+			assertNotNull(payloadOut);
+			//assertEquals(CharStreams.toString(new InputStreamReader(payloadOut.getInput(), "UTF-8")),value);
+			//byte[] _bytes = ByteStreams.toByteArray(payloadOut.getInput());
+			tmpFileOut = new File(Files.createTempDir(),"temp.txt");
+			fos = new FileOutputStream(tmpFileOut);
+			ByteStreams.copy(payloadOut.getInput(), fos);
+			fos.flush();
+			fos.close();
+			assertEquals(Files.equal(tmpFileOut, tmpFileIn),true);
+			tmpFileOut.delete();
+			
+			dataNonCDMIContentTypeApi.deleteDataObject(containerName, dataObjectNameIn);
+			assertEquals(containerApi.getContainer(containerName)
+					.getChildren().contains(dataObjectNameIn), false);
+
+			// exercise create data object with none cdmi put with text file payload file.
+			inFile = new File(System.getProperty("user.dir")
+					+ "/src/test/resources/container.json");
+			assertEquals(true, inFile.isFile());
+			payloadIn = new FilePayload(inFile);
+			payloadIn.setContentMetadata(BaseMutableContentMetadata.fromContentMetadata(payloadIn.getContentMetadata().toBuilder()
+					.contentType(MediaType.JSON_UTF_8.toString())
+					.build()));
+			
+			dataNonCDMIContentTypeApi.createDataObject(containerName, inFile.getName(),
+					payloadIn);
+			System.out.println(containerApi.getContainer(containerName));
+			dataObject = dataApi.getDataObject(containerName,
+					inFile.getName());
+			assertNotNull(dataObject);
+			System.out.println(dataObject);
+			//System.out.println("value: " + dataObject.getValueAsString());
+			//assertEquals(dataObject.getValueAsString(), value);
+			tmpFileOut = dataObject.getValueAsFile(Files.createTempDir());
+			assertEquals(true, Files.equal(tmpFileOut, inFile));
+			tmpFileOut.delete();
+			assertEquals(dataObject.getUserMetadata().isEmpty(), true);
+			//System.out.println("My Metadata: "+dataObject.getUserMetadata());
+			assertEquals(
+					Integer.parseInt(dataObject.getSystemMetadata().get(
+							"cdmi_size")), inFile.length());
+			assertEquals(dataObject.getObjectName(), inFile.getName());
+			assertEquals(dataObject.getObjectType(), "application/cdmi-object");
+			assertEquals(dataObject.getParentURI(), "/" + containerName);
+			assertEquals(containerApi.getContainer(containerName)
+					.getChildren().contains(inFile.getName()), true);
+			dataApi.deleteDataObject(containerName, inFile.getName());
+			assertEquals(containerApi.getContainer(containerName)
+					.getChildren().contains(dataObjectNameIn), false);
+			
+			// exercise create data object with none cdmi put with text file payload file.
+			//inFile = new File(System.getProperty("user.dir")
+			//		+ "/src/test/resources/Jellyfish.jpg");  // takes too long when working from home
+			inFile = new File(System.getProperty("user.dir")
+					+ "/src/test/resources/yellow-flowers.jpg");
+			assertEquals(true, inFile.isFile());
+			payloadIn = new FilePayload(inFile);
+			payloadIn.setContentMetadata(BaseMutableContentMetadata.fromContentMetadata(payloadIn.getContentMetadata().toBuilder()
+					.contentType(MediaType.JPEG.toString())
+					.build()));			
+			dataNonCDMIContentTypeApi.createDataObject(containerName, inFile.getName(),
+					payloadIn);
+			System.out.println(containerApi.getContainer(containerName));
+			//note dataApi.getDataObject when the data object is not a string
+			payloadOut = dataNonCDMIContentTypeApi.getDataObjectValue(containerName, inFile.getName());
+			assertNotNull(payloadOut);
+			tmpFileOut = new File(Files.createTempDir(),"temp.jpg");
+			fos = new FileOutputStream(tmpFileOut);
+			ByteStreams.copy(payloadOut.getInput(), fos);
+			fos.flush();
+			fos.close();
+			assertEquals(Files.equal(tmpFileOut, inFile),true);
+			tmpFileOut.delete();
+			
+			assertEquals(containerApi.getContainer(containerName)
+					.getChildren().contains(inFile.getName()), true);
+			dataApi.deleteDataObject(containerName, inFile.getName());
+			assertEquals(containerApi.getContainer(containerName)
+					.getChildren().contains(inFile.getName()), false);
+			
+
+			// exercise create data object with none cdmi put with payload inputStream riginating from string.
+			value = "Hello CDMI World non-cdmi inputStream originating from string";
+			is = new ByteArrayInputStream(value.getBytes());
+			payloadIn = new InputStreamPayload(is);
+			payloadIn.setContentMetadata(BaseMutableContentMetadata.fromContentMetadata(payloadIn.getContentMetadata().toBuilder()
+					.contentType(MediaType.PLAIN_TEXT_UTF_8.toString())
+					.contentLength(new Long(value.length()))
+					.build()));
+			dataNonCDMIContentTypeApi.createDataObject(containerName, dataObjectNameIn,
+					payloadIn);
+			System.out.println(containerApi.getContainer(containerName));
+			dataObject = dataApi.getDataObject(containerName,
+					dataObjectNameIn);
+			assertNotNull(dataObject);
+			System.out.println(dataObject);
+			System.out.println("value: " + dataObject.getValueAsString());
+			assertEquals(dataObject.getValueAsString(), value);
+			assertNotNull(dataObject.getValueAsInputSupplier());
+			assertEquals(CharStreams.toString(CharStreams.newReaderSupplier(dataObject
+					.getValueAsInputSupplier(Charsets.UTF_8),Charsets.UTF_8)), value);
+			assertEquals(dataObject.getUserMetadata().isEmpty(), true);
+			System.out.println("My Metadata: "+dataObject.getUserMetadata());
+			assertEquals(
+					Integer.parseInt(dataObject.getSystemMetadata().get(
+							"cdmi_size")), value.length());
+			assertEquals(dataObject.getObjectName(), dataObjectNameIn);
+			assertEquals(dataObject.getObjectType(), "application/cdmi-object");
+			assertEquals(dataObject.getParentURI(), "/" + containerName);
+			assertEquals(containerApi.getContainer(containerName)
+					.getChildren().contains(dataObjectNameIn), true);
+			dataNonCDMIContentTypeApi.deleteDataObject(containerName, dataObjectNameIn);
+			assertEquals(containerApi.getContainer(containerName)
+					.getChildren().contains(dataObjectNameIn), false);	
+
+			// exercise create data object with none cdmi put with payload inputStream originating from jpeg file.			
+			inFile = new File(System.getProperty("user.dir")
+					+ "/src/test/resources/yellow-flowers.jpg");
+			assertEquals(true, inFile.isFile());
+			FileInputStream fileInputStream = new FileInputStream(inFile);
+			payloadIn = new InputStreamPayload(fileInputStream);
+			payloadIn.setContentMetadata(BaseMutableContentMetadata.fromContentMetadata(payloadIn.getContentMetadata().toBuilder()
+					.contentType(MediaType.JPEG.toString())
+					.contentLength(new Long(inFile.length()))					
+					.build()));			
+			dataNonCDMIContentTypeApi.createDataObject(containerName, inFile.getName(),
+					payloadIn);
+			System.out.println(containerApi.getContainer(containerName));
+			payloadOut = dataNonCDMIContentTypeApi.getDataObjectValue(containerName, inFile.getName());
+			assertNotNull(payloadOut);
+			tmpFileOut = new File(Files.createTempDir(),"temp.jpg");
+			fos = new FileOutputStream(tmpFileOut);
+			ByteStreams.copy(payloadOut.getInput(), fos);
+			fos.flush();
+			fos.close();
+			assertEquals(Files.equal(tmpFileOut, inFile),true);
+			tmpFileOut.delete();
+			
+			assertEquals(containerApi.getContainer(containerName)
+					.getChildren().contains(inFile.getName()), true);
+			dataApi.deleteDataObject(containerName, inFile.getName());
+			assertEquals(containerApi.getContainer(containerName)
+					.getChildren().contains(inFile.getName()), false);			
+
+			// exercise get with none cdmi get range.
+			value = "Hello CDMI World non-cdmi String";
+			payloadIn = new StringPayload(value);
+			payloadIn.setContentMetadata(BaseMutableContentMetadata.fromContentMetadata(payloadIn.getContentMetadata().toBuilder()
+					.contentType(MediaType.PLAIN_TEXT_UTF_8.toString())
+					.build()));
+			dataNonCDMIContentTypeApi.createDataObject(containerName, dataObjectNameIn,
+					payloadIn);
+
+			payloadOut = dataNonCDMIContentTypeApi.getDataObjectValue(containerName, dataObjectNameIn, "bytes=0-10");
+			assertNotNull(payloadOut);
+			assertEquals(CharStreams.toString(new InputStreamReader(payloadOut.getInput(), "UTF-8")),value.substring(0, 11));
+			assertEquals(payloadOut.getContentMetadata().getContentLength(),new Long(11));
+			
+			payloadOut = dataNonCDMIContentTypeApi.getDataObjectValue(containerName, dataObjectNameIn, "bytes=11-20");
+			assertNotNull(payloadOut);
+			assertEquals(CharStreams.toString(new InputStreamReader(payloadOut.getInput(), "UTF-8")),value.substring(11, 21));
+			assertEquals(payloadOut.getContentMetadata().getContentLength(),new Long(10));	
+			
+			dataNonCDMIContentTypeApi.deleteDataObject(containerName, dataObjectNameIn);
+			assertEquals(containerApi.getContainer(containerName)
+					.getChildren().contains(dataObjectNameIn), false);
+
+			// exercise create data object with none cdmi partial.
+			// server does not actually support cdmi partial but
+			// trace allows me to see that request was constructed properly
+			value = "Hello CDMI World non-cdmi String";
+			payloadIn = new StringPayload(value);
+			payloadIn.setContentMetadata(BaseMutableContentMetadata.fromContentMetadata(payloadIn.getContentMetadata().toBuilder()
+					.contentType(MediaType.PLAIN_TEXT_UTF_8.toString())
+					.build()));
+			dataNonCDMIContentTypeApi.createDataObjectPartial(containerName, dataObjectNameIn,
+					payloadIn);
+			payloadOut = dataNonCDMIContentTypeApi.getDataObjectValue(containerName, dataObjectNameIn);
+			assertNotNull(payloadOut);
+			System.out.println("payload "+payloadOut);
+			
+			dataNonCDMIContentTypeApi.createDataObjectPartial(containerName, dataObjectNameIn,
+					payloadIn);
+			payloadOut = dataNonCDMIContentTypeApi.getDataObjectValue(containerName, dataObjectNameIn);
+			assertNotNull(payloadOut);
+			System.out.println("payload "+payloadOut);
+
+			
+			
+			dataNonCDMIContentTypeApi.createDataObject(containerName, dataObjectNameIn,
+					payloadIn);
+
+
+			payloadOut = dataNonCDMIContentTypeApi.getDataObjectValue(containerName, dataObjectNameIn);
+			assertNotNull(payloadOut);
+			System.out.println("payload "+payloadOut);
+		
+	
+		} finally {
+			tmpFileIn.delete();
+			containerApi.deleteContainer(containerName);
+
+		}
+
+	}
+
+}
diff --git a/labs/cdmi/src/test/resources/Jellyfish.jpg b/labs/cdmi/src/test/resources/Jellyfish.jpg
new file mode 100644
index 0000000..fa4fd41
--- /dev/null
+++ b/labs/cdmi/src/test/resources/Jellyfish.jpg
Binary files differ
diff --git a/labs/cdmi/src/test/resources/yellow-flowers.jpg b/labs/cdmi/src/test/resources/yellow-flowers.jpg
new file mode 100644
index 0000000..810b7c3
--- /dev/null
+++ b/labs/cdmi/src/test/resources/yellow-flowers.jpg
Binary files differ
diff --git a/labs/fgcp-au/pom.xml b/labs/fgcp-au/pom.xml
new file mode 100644
index 0000000..e32cc3d
--- /dev/null
+++ b/labs/fgcp-au/pom.xml
@@ -0,0 +1,175 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+  Licensed to jclouds, Inc. (jclouds) under one or more
+  contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  jclouds licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing,
+  software distributed under the License is distributed on an
+  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  KIND, either express or implied.  See the License for the
+  specific language governing permissions and limitations
+  under the License.
+
+-->
+<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/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>org.jclouds</groupId>
+        <artifactId>jclouds-project</artifactId>
+        <version>1.5.0-SNAPSHOT</version>
+        <relativePath>../../project/pom.xml</relativePath>
+    </parent>
+    <groupId>org.jclouds.labs</groupId>
+    <artifactId>fgcp-au</artifactId>
+    <name>jclouds Fujitsu Global Cloud Platform AU provider</name>
+    <description>jclouds components to access Fujitsu Global Cloud Platform in Australia</description>
+    <url>http://globalcloud.fujitsu.com.au</url>
+
+    <packaging>bundle</packaging>
+
+    <developers>
+        <developer>
+            <name>Dies Koper</name>
+            <id>dkoper</id>
+            <email>diesk -at- fast -dot- au -dot- fujitsu -dot- com</email>
+            <organization>Fujitsu</organization>
+            <roles>
+                <role>Java Developer</role>
+            </roles>
+            <timezone>+10</timezone>
+        </developer>
+    </developers>
+
+    <properties>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+        <test.fgcp-au.endpoint>https://api.globalcloud.fujitsu.com.au/ovissapi/endpoint</test.fgcp-au.endpoint>
+        <test.fgcp-au.apiversion>2011-01-31</test.fgcp-au.apiversion>
+        <test.fgcp-au.build-version></test.fgcp-au.build-version>
+        <test.fgcp-au.identity>fgcp-id</test.fgcp-au.identity>
+        <test.fgcp-au.credential>fgcp-cred</test.fgcp-au.credential>
+        <test.fgcp-au.image-id />
+        <test.fgcp-au.image.login-user />
+        <test.fgcp-au.image.authenticate-sudo />
+        <jclouds.osgi.export>org.jclouds.fujitsu.fgcp*;version="${project.version}"</jclouds.osgi.export>
+        <jclouds.osgi.import>
+          org.jclouds.providers*;version="${project.version}",
+          *
+        </jclouds.osgi.import>
+    </properties>
+
+
+    <dependencies>
+        <dependency>
+            <groupId>org.jclouds</groupId>
+            <artifactId>jclouds-compute</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <!--<dependency>-->
+            <!--<groupId>org.jclouds.provider</groupId>-->
+            <!--<artifactId>fgcp</artifactId>-->
+            <!--<version>${project.version}</version>-->
+        <!--</dependency>-->
+        <dependency>
+            <groupId>org.bouncycastle</groupId>
+            <artifactId>bcprov-jdk16</artifactId>
+            <version>1.46</version>
+            <optional>true</optional>
+        </dependency>
+        <dependency>
+            <groupId>org.jclouds.driver</groupId>
+            <artifactId>jclouds-sshj</artifactId>
+            <version>${project.version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.jclouds.driver</groupId>
+            <artifactId>jclouds-log4j</artifactId>
+            <version>${project.version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.jclouds</groupId>
+            <artifactId>jclouds-core</artifactId>
+            <version>${project.version}</version>
+            <type>test-jar</type>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.jclouds</groupId>
+            <artifactId>jclouds-compute</artifactId>
+            <version>${project.version}</version>
+            <type>test-jar</type>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.testng</groupId>
+            <artifactId>testng</artifactId>
+            <version>6.0.1</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.easymock</groupId>
+            <artifactId>easymockclassextension</artifactId>
+            <version>2.4</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.jclouds.labs</groupId>
+            <artifactId>fgcp</artifactId>
+            <version>${project.version}</version>
+            <type>jar</type>
+        </dependency>
+        <dependency>
+            <groupId>org.jclouds.labs</groupId>
+            <artifactId>fgcp</artifactId>
+            <version>${project.version}</version>
+            <type>test-jar</type>
+            <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>
+                                    <systemPropertyVariables>
+                                        <test.fgcp-au.identity>${test.fgcp-au.identity}</test.fgcp-au.identity>
+                                        <test.fgcp-au.credential>${test.fgcp-au.credential}</test.fgcp-au.credential>
+                                        <test.fgcp-au.endpoint>${test.fgcp-au.endpoint}</test.fgcp-au.endpoint>
+                                        <test.fgcp-au.apiversion>${test.fgcp-au.apiversion}</test.fgcp-au.apiversion>
+                                        <test.fgcp-au.build-version>${test.fgcp-au.build-version}</test.fgcp-au.build-version>
+                                        <test.fgcp-au.image-id>${test.fgcp-au.image-id}</test.fgcp-au.image-id>
+                                        <test.fgcp-au.image.login-user>${test.fgcp-au.image.login-user}</test.fgcp-au.image.login-user>
+                                        <test.fgcp-au.image.authenticate-sudo>${test.fgcp-au.image.authenticate-sudo}</test.fgcp-au.image.authenticate-sudo>
+                                    </systemPropertyVariables>
+                                </configuration>
+                            </execution>
+                        </executions>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+    </profiles>
+
+</project>
diff --git a/labs/fgcp-au/src/main/java/org/jclouds/fujitsu/fgcp/FGCPAUProviderMetadata.java b/labs/fgcp-au/src/main/java/org/jclouds/fujitsu/fgcp/FGCPAUProviderMetadata.java
new file mode 100644
index 0000000..b17d6ca
--- /dev/null
+++ b/labs/fgcp-au/src/main/java/org/jclouds/fujitsu/fgcp/FGCPAUProviderMetadata.java
@@ -0,0 +1,77 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.fujitsu.fgcp;
+
+import java.net.URI;
+
+import org.jclouds.providers.ProviderMetadata;
+import org.jclouds.providers.internal.BaseProviderMetadata;
+
+/**
+ * Implementation of {@link org.jclouds.providers.ProviderMetadata} for FGCP.
+ * 
+ * @author Dies Koper
+ */
+public class FGCPAUProviderMetadata extends FGCPProviderMetadata {
+
+    public static Builder builder() {
+        return new Builder();
+    }
+
+    public FGCPAUProviderMetadata() {
+        super(builder());
+    }
+
+    public FGCPAUProviderMetadata(Builder builder) {
+        super(builder);
+    }
+
+    @Override
+    public Builder toBuilder() {
+        return builder().fromProviderMetadata(this);
+    }
+
+    public static class Builder extends BaseProviderMetadata.Builder {
+
+        protected Builder() {
+            id("fgcp-au")
+                    .name("Fujitsu Global Cloud Platform (FGCP) - AU")
+                    .apiMetadata(new FGCPApiMetadata())
+                    .homepage(
+                            URI.create("http://www.fujitsu.com/global/solutions/cloud/solutions/global-cloud-platform/index.html"))
+                    .console(URI.create("http://globalcloud.fujitsu.com.au"))
+                    .defaultProperties(FGCPApiMetadata.defaultProperties())
+                    .iso3166Codes("AU-NSW")
+                    .endpoint(
+                            "https://api.globalcloud.fujitsu.com.au/ovissapi/endpoint")
+                    .defaultProperties(FGCPProviderMetadata.defaultProperties());
+        }
+
+        @Override
+        public FGCPAUProviderMetadata build() {
+            return new FGCPAUProviderMetadata(this);
+        }
+
+        @Override
+        public Builder fromProviderMetadata(ProviderMetadata in) {
+            super.fromProviderMetadata(in);
+            return this;
+        }
+    }
+}
\ No newline at end of file
diff --git a/labs/fgcp-au/src/main/resources/META-INF/services/org.jclouds.providers.ProviderMetadata b/labs/fgcp-au/src/main/resources/META-INF/services/org.jclouds.providers.ProviderMetadata
new file mode 100644
index 0000000..83cbc20
--- /dev/null
+++ b/labs/fgcp-au/src/main/resources/META-INF/services/org.jclouds.providers.ProviderMetadata
@@ -0,0 +1 @@
+org.jclouds.fujitsu.fgcp.FGCPAUProviderMetadata
diff --git a/labs/fgcp-au/src/test/java/org/jclouds/fujitsu/fgcp/FGCPAUProviderTest.java b/labs/fgcp-au/src/test/java/org/jclouds/fujitsu/fgcp/FGCPAUProviderTest.java
new file mode 100644
index 0000000..9a2ddbc
--- /dev/null
+++ b/labs/fgcp-au/src/test/java/org/jclouds/fujitsu/fgcp/FGCPAUProviderTest.java
@@ -0,0 +1,34 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.fujitsu.fgcp;
+
+import org.jclouds.providers.internal.BaseProviderMetadataTest;
+import org.testng.annotations.Test;
+
+/**
+ * @author Dies Koper
+ */
+@Test(groups = "unit", testName = "FGCPAUProviderTest")
+public class FGCPAUProviderTest extends BaseProviderMetadataTest {
+
+   public FGCPAUProviderTest() {
+      super(new FGCPAUProviderMetadata(), new FGCPApiMetadata());
+   }
+
+}
diff --git a/labs/fgcp-au/src/test/java/org/jclouds/fujitsu/fgcp/compute/FGCPAUTemplateBuilderLiveTest.java b/labs/fgcp-au/src/test/java/org/jclouds/fujitsu/fgcp/compute/FGCPAUTemplateBuilderLiveTest.java
new file mode 100644
index 0000000..30f12de
--- /dev/null
+++ b/labs/fgcp-au/src/test/java/org/jclouds/fujitsu/fgcp/compute/FGCPAUTemplateBuilderLiveTest.java
@@ -0,0 +1,43 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.fujitsu.fgcp.compute;
+
+import java.util.Set;
+
+import org.testng.annotations.Test;
+
+import com.google.common.collect.ImmutableSet;
+
+/**
+ * @author Dies Koper
+ * 
+ */
+@Test(groups = "live", enabled = true, singleThreaded = true, testName = "FGCPAUTemplateBuilderLiveTest")
+public class FGCPAUTemplateBuilderLiveTest extends
+        FGCPBaseTemplateBuilderLiveTest {
+
+    public FGCPAUTemplateBuilderLiveTest() {
+        provider = "fgcp-au";
+    }
+
+    @Override
+    protected Set<String> getIso3166Codes() {
+        return ImmutableSet.<String> of("AU-NSW");
+    }
+}
diff --git a/labs/fgcp-au/src/test/java/org/jclouds/fujitsu/fgcp/compute/config/FGCPAUComputeServiceLiveTest.java b/labs/fgcp-au/src/test/java/org/jclouds/fujitsu/fgcp/compute/config/FGCPAUComputeServiceLiveTest.java
new file mode 100644
index 0000000..49c23ff
--- /dev/null
+++ b/labs/fgcp-au/src/test/java/org/jclouds/fujitsu/fgcp/compute/config/FGCPAUComputeServiceLiveTest.java
@@ -0,0 +1,37 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.fujitsu.fgcp.compute.config;
+
+
+import org.testng.annotations.Test;
+
+
+/**
+ * @author Dies Koper
+ *
+ */
+@Test(groups = "live", enabled = true, singleThreaded = true, testName = "FGCPAUComputeServiceLiveTest")
+public class FGCPAUComputeServiceLiveTest extends FGCPBaseComputeServiceLiveTest {
+
+    @Override
+    public void setServiceDefaults() {
+        provider = "fgcp-au";
+    }
+
+}
diff --git a/labs/fgcp-de/pom.xml b/labs/fgcp-de/pom.xml
new file mode 100644
index 0000000..6aa954a
--- /dev/null
+++ b/labs/fgcp-de/pom.xml
@@ -0,0 +1,175 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+  Licensed to jclouds, Inc. (jclouds) under one or more
+  contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  jclouds licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing,
+  software distributed under the License is distributed on an
+  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  KIND, either express or implied.  See the License for the
+  specific language governing permissions and limitations
+  under the License.
+
+-->
+<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/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>org.jclouds</groupId>
+        <artifactId>jclouds-project</artifactId>
+        <version>1.5.0-SNAPSHOT</version>
+        <relativePath>../../project/pom.xml</relativePath>
+    </parent>
+    <groupId>org.jclouds.labs</groupId>
+    <artifactId>fgcp-de</artifactId>
+    <name>jclouds Fujitsu Global Cloud Platform DE provider</name>
+    <description>jclouds components to access Fujitsu Global Cloud Platform in Germany</description>
+    <url>http://globalcloud.de.fujitsu.com</url>
+
+    <packaging>bundle</packaging>
+
+    <developers>
+        <developer>
+            <name>Dies Koper</name>
+            <id>dkoper</id>
+            <email>diesk -at- fast -dot- au -dot- fujitsu -dot- com</email>
+            <organization>Fujitsu</organization>
+            <roles>
+                <role>Java Developer</role>
+            </roles>
+            <timezone>+10</timezone>
+        </developer>
+    </developers>
+
+    <properties>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+        <test.fgcp-de.endpoint>https://api.globalcloud.de.fujitsu.com/ovissapi/endpoint</test.fgcp-de.endpoint>
+        <test.fgcp-de.apiversion>2011-01-31</test.fgcp-de.apiversion>
+        <test.fgcp-de.build-version></test.fgcp-de.build-version>
+        <test.fgcp-de.identity>fgcp-id</test.fgcp-de.identity>
+        <test.fgcp-de.credential>fgcp-cred</test.fgcp-de.credential>
+        <test.fgcp-de.image-id />
+        <test.fgcp-de.image.login-user />
+        <test.fgcp-de.image.authenticate-sudo />
+        <jclouds.osgi.export>org.jclouds.fujitsu.fgcp*;version="${project.version}"</jclouds.osgi.export>
+        <jclouds.osgi.import>
+          org.jclouds.providers*;version="${project.version}",
+          *
+        </jclouds.osgi.import>
+    </properties>
+
+
+    <dependencies>
+        <dependency>
+            <groupId>org.jclouds</groupId>
+            <artifactId>jclouds-compute</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <!--<dependency>-->
+            <!--<groupId>org.jclouds.provider</groupId>-->
+            <!--<artifactId>fgcp</artifactId>-->
+            <!--<version>${project.version}</version>-->
+        <!--</dependency>-->
+        <dependency>
+            <groupId>org.bouncycastle</groupId>
+            <artifactId>bcprov-jdk16</artifactId>
+            <version>1.46</version>
+            <optional>true</optional>
+        </dependency>
+        <dependency>
+            <groupId>org.jclouds.driver</groupId>
+            <artifactId>jclouds-sshj</artifactId>
+            <version>${project.version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.jclouds.driver</groupId>
+            <artifactId>jclouds-log4j</artifactId>
+            <version>${project.version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.jclouds</groupId>
+            <artifactId>jclouds-core</artifactId>
+            <version>${project.version}</version>
+            <type>test-jar</type>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.jclouds</groupId>
+            <artifactId>jclouds-compute</artifactId>
+            <version>${project.version}</version>
+            <type>test-jar</type>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.testng</groupId>
+            <artifactId>testng</artifactId>
+            <version>6.0.1</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.easymock</groupId>
+            <artifactId>easymockclassextension</artifactId>
+            <version>2.4</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.jclouds.labs</groupId>
+            <artifactId>fgcp</artifactId>
+            <version>${project.version}</version>
+            <type>jar</type>
+        </dependency>
+        <dependency>
+            <groupId>org.jclouds.labs</groupId>
+            <artifactId>fgcp</artifactId>
+            <version>${project.version}</version>
+            <type>test-jar</type>
+            <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>
+                                    <systemPropertyVariables>
+                                        <test.fgcp-de.identity>${test.fgcp-de.identity}</test.fgcp-de.identity>
+                                        <test.fgcp-de.credential>${test.fgcp-de.credential}</test.fgcp-de.credential>
+                                        <test.fgcp-de.endpoint>${test.fgcp-de.endpoint}</test.fgcp-de.endpoint>
+                                        <test.fgcp-de.apiversion>${test.fgcp-de.apiversion}</test.fgcp-de.apiversion>
+                                        <test.fgcp-de.build-version>${test.fgcp-de.build-version}</test.fgcp-de.build-version>
+                                        <test.fgcp-de.image-id>${test.fgcp-de.image-id}</test.fgcp-de.image-id>
+                                        <test.fgcp-de.image.login-user>${test.fgcp-de.image.login-user}</test.fgcp-de.image.login-user>
+                                        <test.fgcp-de.image.authenticate-sudo>${test.fgcp-de.image.authenticate-sudo}</test.fgcp-de.image.authenticate-sudo>
+                                    </systemPropertyVariables>
+                                </configuration>
+                            </execution>
+                        </executions>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+    </profiles>
+
+</project>
diff --git a/labs/fgcp-de/src/main/java/org/jclouds/fujitsu/fgcp/FGCPDEProviderMetadata.java b/labs/fgcp-de/src/main/java/org/jclouds/fujitsu/fgcp/FGCPDEProviderMetadata.java
new file mode 100644
index 0000000..db087a5
--- /dev/null
+++ b/labs/fgcp-de/src/main/java/org/jclouds/fujitsu/fgcp/FGCPDEProviderMetadata.java
@@ -0,0 +1,79 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.fujitsu.fgcp;
+
+import java.net.URI;
+
+import org.jclouds.providers.ProviderMetadata;
+import org.jclouds.providers.internal.BaseProviderMetadata;
+
+/**
+ * Implementation of {@link org.jclouds.providers.ProviderMetadata} for FGCP.
+ * 
+ * @author Dies Koper
+ */
+public class FGCPDEProviderMetadata extends FGCPProviderMetadata {
+
+    private static final long serialVersionUID = -8498457904032259345L;
+
+    public static Builder builder() {
+        return new Builder();
+    }
+
+    public FGCPDEProviderMetadata() {
+        super(builder());
+    }
+
+    public FGCPDEProviderMetadata(Builder builder) {
+        super(builder);
+    }
+
+    @Override
+    public Builder toBuilder() {
+        return builder().fromProviderMetadata(this);
+    }
+
+    public static class Builder extends BaseProviderMetadata.Builder {
+
+        protected Builder() {
+            id("fgcp-de")
+                    .name("Fujitsu Global Cloud Platform (FGCP) - DE")
+                    .apiMetadata(new FGCPApiMetadata())
+                    .homepage(
+                            URI.create("http://www.fujitsu.com/global/solutions/cloud/solutions/global-cloud-platform/index.html"))
+                    .console(URI.create("http://globalcloud.de.fujitsu.com"))
+                    .defaultProperties(FGCPApiMetadata.defaultProperties())
+                    .iso3166Codes("DE-BY")
+                    .endpoint(
+                            "https://api.globalcloud.de.fujitsu.com/ovissapi/endpoint")
+                    .defaultProperties(FGCPProviderMetadata.defaultProperties());
+        }
+
+        @Override
+        public FGCPDEProviderMetadata build() {
+            return new FGCPDEProviderMetadata(this);
+        }
+
+        @Override
+        public Builder fromProviderMetadata(ProviderMetadata in) {
+            super.fromProviderMetadata(in);
+            return this;
+        }
+    }
+}
\ No newline at end of file
diff --git a/labs/fgcp-de/src/main/resources/META-INF/services/org.jclouds.providers.ProviderMetadata b/labs/fgcp-de/src/main/resources/META-INF/services/org.jclouds.providers.ProviderMetadata
new file mode 100644
index 0000000..9e952cb
--- /dev/null
+++ b/labs/fgcp-de/src/main/resources/META-INF/services/org.jclouds.providers.ProviderMetadata
@@ -0,0 +1 @@
+org.jclouds.fujitsu.fgcp.FGCPDEProviderMetadata
diff --git a/labs/fgcp-de/src/test/java/org/jclouds/fujitsu/fgcp/FGCPDEProviderTest.java b/labs/fgcp-de/src/test/java/org/jclouds/fujitsu/fgcp/FGCPDEProviderTest.java
new file mode 100644
index 0000000..99b37d2
--- /dev/null
+++ b/labs/fgcp-de/src/test/java/org/jclouds/fujitsu/fgcp/FGCPDEProviderTest.java
@@ -0,0 +1,34 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.fujitsu.fgcp;
+
+import org.jclouds.providers.internal.BaseProviderMetadataTest;
+import org.testng.annotations.Test;
+
+/**
+ * @author Dies Koper
+ */
+@Test(groups = "unit", testName = "FGCPDEProviderTest")
+public class FGCPDEProviderTest extends BaseProviderMetadataTest {
+
+   public FGCPDEProviderTest() {
+      super(new FGCPDEProviderMetadata(), new FGCPApiMetadata());
+   }
+
+}
diff --git a/labs/fgcp-de/src/test/java/org/jclouds/fujitsu/fgcp/compute/FGCPDETemplateBuilderLiveTest.java b/labs/fgcp-de/src/test/java/org/jclouds/fujitsu/fgcp/compute/FGCPDETemplateBuilderLiveTest.java
new file mode 100644
index 0000000..0894978
--- /dev/null
+++ b/labs/fgcp-de/src/test/java/org/jclouds/fujitsu/fgcp/compute/FGCPDETemplateBuilderLiveTest.java
@@ -0,0 +1,43 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.fujitsu.fgcp.compute;
+
+import java.util.Set;
+
+import org.testng.annotations.Test;
+
+import com.google.common.collect.ImmutableSet;
+
+/**
+ * @author Dies Koper
+ * 
+ */
+@Test(groups = "live", enabled = true, singleThreaded = true, testName = "FGCPDETemplateBuilderLiveTest")
+public class FGCPDETemplateBuilderLiveTest extends
+        FGCPBaseTemplateBuilderLiveTest {
+
+    public FGCPDETemplateBuilderLiveTest() {
+        provider = "fgcp-de";
+    }
+
+    @Override
+    protected Set<String> getIso3166Codes() {
+        return ImmutableSet.<String> of("DE-BY");
+    }
+}
diff --git a/labs/fgcp-de/src/test/java/org/jclouds/fujitsu/fgcp/compute/config/FGCPDEComputeServiceLiveTest.java b/labs/fgcp-de/src/test/java/org/jclouds/fujitsu/fgcp/compute/config/FGCPDEComputeServiceLiveTest.java
new file mode 100644
index 0000000..f0de559
--- /dev/null
+++ b/labs/fgcp-de/src/test/java/org/jclouds/fujitsu/fgcp/compute/config/FGCPDEComputeServiceLiveTest.java
@@ -0,0 +1,37 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.fujitsu.fgcp.compute.config;
+
+
+import org.testng.annotations.Test;
+
+
+/**
+ * @author Dies Koper
+ *
+ */
+@Test(groups = "live", enabled = true, singleThreaded = true, testName = "FGCPDEComputeServiceLiveTest")
+public class FGCPDEComputeServiceLiveTest extends FGCPBaseComputeServiceLiveTest {
+
+    @Override
+    public void setServiceDefaults() {
+        provider = "fgcp-de";
+    }
+
+}
diff --git a/labs/fgcp/pom.xml b/labs/fgcp/pom.xml
new file mode 100644
index 0000000..cc1e81f
--- /dev/null
+++ b/labs/fgcp/pom.xml
@@ -0,0 +1,169 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+  Licensed to jclouds, Inc. (jclouds) under one or more
+  contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  jclouds licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing,
+  software distributed under the License is distributed on an
+  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  KIND, either express or implied.  See the License for the
+  specific language governing permissions and limitations
+  under the License.
+
+-->
+<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/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>org.jclouds</groupId>
+        <artifactId>jclouds-project</artifactId>
+        <version>1.5.0-SNAPSHOT</version>
+        <relativePath>../../project/pom.xml</relativePath>
+    </parent>
+    <groupId>org.jclouds.labs</groupId>
+    <artifactId>fgcp</artifactId>
+    <name>jclouds Fujitsu Global Cloud Platform</name>
+    <description>jclouds components to access Fujitsu Global Cloud Platform</description>
+
+    <packaging>bundle</packaging>
+
+    <developers>
+        <developer>
+            <name>Dies Koper</name>
+            <id>dkoper</id>
+            <email>diesk -at- fast -dot- au -dot- fujitsu -dot- com</email>
+            <organization>Fujitsu</organization>
+            <roles>
+                <role>Java Developer</role>
+            </roles>
+            <timezone>+10</timezone>
+        </developer>
+    </developers>
+
+    <properties>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+        <test.fgcp-au.endpoint>https://api.globalcloud.fujitsu.com.au/ovissapi/endpoint</test.fgcp-au.endpoint>
+        <test.fgcp-au.apiversion>2011-01-31</test.fgcp-au.apiversion>
+        <test.fgcp-au.build-version></test.fgcp-au.build-version>
+        <test.fgcp-au.identity>fgcp-id</test.fgcp-au.identity>
+        <test.fgcp-au.credential>fgcp-cred</test.fgcp-au.credential>
+        <test.fgcp-au.image-id>IMG_3c9820_71OW9NZC268</test.fgcp-au.image-id><!-- CentOS 6.2 64bit(EN) in AU -->
+        <test.fgcp-au.image.login-user />
+        <test.fgcp-au.image.authenticate-sudo />
+        <jclouds.osgi.export>org.jclouds.fujitsu.fgcp*;version="${project.version}"</jclouds.osgi.export>
+        <jclouds.osgi.import>
+          org.jclouds.compute.internal;version="${project.version}",
+          org.jclouds.rest.internal;version="${project.version}",
+          org.jclouds*;version="${project.version}",
+          *
+        </jclouds.osgi.import>
+    </properties>
+
+
+    <dependencies>
+        <dependency>
+            <groupId>org.jclouds</groupId>
+            <artifactId>jclouds-compute</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <!--<dependency>-->
+            <!--<groupId>org.jclouds.provider</groupId>-->
+            <!--<artifactId>fgcp</artifactId>-->
+            <!--<version>${project.version}</version>-->
+        <!--</dependency>-->
+        <dependency>
+            <groupId>org.bouncycastle</groupId>
+            <artifactId>bcprov-jdk16</artifactId>
+            <version>1.46</version>
+            <optional>true</optional>
+        </dependency>
+        <dependency>
+            <groupId>org.jclouds.driver</groupId>
+            <artifactId>jclouds-sshj</artifactId>
+            <version>${project.version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.jclouds.driver</groupId>
+            <artifactId>jclouds-log4j</artifactId>
+            <version>${project.version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.jclouds</groupId>
+            <artifactId>jclouds-core</artifactId>
+            <version>${project.version}</version>
+            <type>test-jar</type>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.jclouds</groupId>
+            <artifactId>jclouds-compute</artifactId>
+            <version>${project.version}</version>
+            <type>test-jar</type>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.testng</groupId>
+            <artifactId>testng</artifactId>
+            <version>6.0.1</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.easymock</groupId>
+            <artifactId>easymockclassextension</artifactId>
+            <version>2.4</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>ch.qos.logback</groupId>
+            <artifactId>logback-classic</artifactId>
+            <version>1.0.0</version>
+        </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.fgcp-au.identity>${test.fgcp-au.identity}</test.fgcp-au.identity>
+                                        <test.fgcp-au.credential>${test.fgcp-au.credential}</test.fgcp-au.credential>
+                                        <test.fgcp-au.endpoint>${test.fgcp-au.endpoint}</test.fgcp-au.endpoint>
+                                        <test.fgcp-au.apiversion>${test.fgcp-au.apiversion}</test.fgcp-au.apiversion>
+                                        <test.fgcp-au.build-version>${test.fgcp-au.build-version}</test.fgcp-au.build-version>
+                                        <test.fgcp-au.image-id>${test.fgcp-au.image-id}</test.fgcp-au.image-id>
+                                        <test.fgcp-au.image.login-user>${test.fgcp-au.image.login-user}</test.fgcp-au.image.login-user>
+                                        <test.fgcp-au.image.authenticate-sudo>${test.fgcp-au.image.authenticate-sudo}</test.fgcp-au.image.authenticate-sudo>
+                                    </systemPropertyVariables>
+                                </configuration>
+                            </execution>
+                        </executions>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+    </profiles>
+
+</project>
diff --git a/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/FGCPApi.java b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/FGCPApi.java
new file mode 100644
index 0000000..54561af
--- /dev/null
+++ b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/FGCPApi.java
@@ -0,0 +1,69 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.fujitsu.fgcp;
+
+import java.util.concurrent.TimeUnit;
+
+import org.jclouds.concurrent.Timeout;
+import org.jclouds.fujitsu.fgcp.services.AdditionalDiskApi;
+import org.jclouds.fujitsu.fgcp.services.DiskImageApi;
+import org.jclouds.fujitsu.fgcp.services.FirewallApi;
+import org.jclouds.fujitsu.fgcp.services.LoadBalancerApi;
+import org.jclouds.fujitsu.fgcp.services.PublicIPAddressApi;
+import org.jclouds.fujitsu.fgcp.services.SystemTemplateApi;
+import org.jclouds.fujitsu.fgcp.services.VirtualDCApi;
+import org.jclouds.fujitsu.fgcp.services.VirtualServerApi;
+import org.jclouds.fujitsu.fgcp.services.VirtualSystemApi;
+import org.jclouds.rest.annotations.Delegate;
+
+/**
+ * Provides synchronous access to FGCP services.
+ * 
+ * @author Dies Koper
+ */
+@Timeout(duration = 180, timeUnit = TimeUnit.SECONDS)
+public interface FGCPApi {
+
+    @Delegate
+    VirtualDCApi getVirtualDCApi();
+
+    @Delegate
+    VirtualSystemApi getVirtualSystemApi();
+
+    @Delegate
+    VirtualServerApi getVirtualServerApi();
+
+    @Delegate
+    AdditionalDiskApi getAdditionalDiskApi();
+
+    @Delegate
+    SystemTemplateApi getSystemTemplateApi();
+
+    @Delegate
+    DiskImageApi getDiskImageApi();
+
+    @Delegate
+    FirewallApi getFirewallApi();
+
+    @Delegate
+    LoadBalancerApi getLoadBalancerApi();
+
+    @Delegate
+    PublicIPAddressApi getPublicIPAddressApi();
+}
diff --git a/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/FGCPApiMetadata.java b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/FGCPApiMetadata.java
new file mode 100644
index 0000000..0f5e9fd
--- /dev/null
+++ b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/FGCPApiMetadata.java
@@ -0,0 +1,99 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.fujitsu.fgcp;
+
+import java.net.URI;
+import java.util.Properties;
+
+import org.jclouds.Constants;
+import org.jclouds.apis.ApiMetadata;
+import org.jclouds.compute.ComputeServiceContext;
+import org.jclouds.fujitsu.fgcp.compute.FGCPRestClientModule;
+import org.jclouds.fujitsu.fgcp.compute.config.FGCPComputeServiceContextModule;
+import org.jclouds.rest.internal.BaseRestApiMetadata;
+
+import com.google.common.collect.ImmutableSet;
+import com.google.common.reflect.TypeToken;
+import com.google.inject.Module;
+
+/**
+ * Implementation of {@link ApiMetadata} for Fujitsu's Global Cloud Platform
+ * (FGCP, FGCP/S5) provider in Australia.
+ * 
+ * @author Dies Koper
+ */
+public class FGCPApiMetadata extends BaseRestApiMetadata {
+
+    @Override
+    public Builder toBuilder() {
+        return new Builder().fromApiMetadata(this);
+    }
+
+    public FGCPApiMetadata() {
+        this(new Builder());
+    }
+
+    protected FGCPApiMetadata(Builder builder) {
+        super(builder);
+    }
+
+    public static Properties defaultProperties() {
+        Properties properties = BaseRestApiMetadata.defaultProperties();
+        // enables peer verification using the CAs bundled with the JRE (or
+        // value of javax.net.ssl.trustStore if set)
+        properties.setProperty(Constants.PROPERTY_TRUST_ALL_CERTS, "false");
+        // properties.setProperty("jclouds.ssh.max-retries", "5");
+        // properties.setProperty("jclouds.ssh.retry-auth", "true");
+        return properties;
+    }
+
+    public static class Builder extends BaseRestApiMetadata.Builder {
+
+        protected Builder() {
+            super(FGCPApi.class, FGCPAsyncApi.class);
+            id("fgcp")
+                    .name("Fujitsu Global Cloud Platform (FGCP)")
+                    .identityName("User certificate (PEM file)")
+                    .credentialName("User certificate password")
+                    .documentation(
+                            URI.create("https://globalcloud.fujitsu.com.au/portala/ctrl/aboutSopManual"))
+                    .version(FGCPAsyncApi.VERSION)
+                    .defaultEndpoint(
+                            "https://api.globalcloud.fujitsu.com.au/ovissapi/endpoint")
+                    .defaultProperties(FGCPApiMetadata.defaultProperties())
+                    .view(TypeToken.of(ComputeServiceContext.class))
+                    .defaultModules(
+                            ImmutableSet.<Class<? extends Module>> of(
+                                    FGCPComputeServiceContextModule.class,
+                                    FGCPRestClientModule.class));
+        }
+
+        @Override
+        public FGCPApiMetadata build() {
+            return new FGCPApiMetadata(this);
+        }
+
+        @Override
+        public Builder fromApiMetadata(ApiMetadata in) {
+            super.fromApiMetadata(in);
+            return this;
+        }
+
+    }
+}
diff --git a/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/FGCPAsyncApi.java b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/FGCPAsyncApi.java
new file mode 100644
index 0000000..9eda1dd
--- /dev/null
+++ b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/FGCPAsyncApi.java
@@ -0,0 +1,66 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.fujitsu.fgcp;
+
+import org.jclouds.fujitsu.fgcp.services.AdditionalDiskAsyncApi;
+import org.jclouds.fujitsu.fgcp.services.DiskImageAsyncApi;
+import org.jclouds.fujitsu.fgcp.services.FirewallAsyncApi;
+import org.jclouds.fujitsu.fgcp.services.LoadBalancerAsyncApi;
+import org.jclouds.fujitsu.fgcp.services.PublicIPAddressAsyncApi;
+import org.jclouds.fujitsu.fgcp.services.SystemTemplateAsyncApi;
+import org.jclouds.fujitsu.fgcp.services.VirtualDCAsyncApi;
+import org.jclouds.fujitsu.fgcp.services.VirtualServerAsyncApi;
+import org.jclouds.fujitsu.fgcp.services.VirtualSystemAsyncApi;
+import org.jclouds.rest.annotations.Delegate;
+
+/**
+ * Provides asynchronous access to FGCP services.
+ * 
+ * @author Dies Koper
+ */
+public interface FGCPAsyncApi {
+    public final static String VERSION = "2012-02-18";
+
+    @Delegate
+    VirtualDCAsyncApi getVirtualDCApi();
+
+    @Delegate
+    VirtualSystemAsyncApi getVirtualSystemApi();
+
+    @Delegate
+    VirtualServerAsyncApi getVirtualServerApi();
+
+    @Delegate
+    AdditionalDiskAsyncApi getAdditionalDiskApi();
+
+    @Delegate
+    SystemTemplateAsyncApi getSystemTemplateApi();
+
+    @Delegate
+    DiskImageAsyncApi getDiskImageApi();
+
+    @Delegate
+    FirewallAsyncApi getFirewallApi();
+
+    @Delegate
+    LoadBalancerAsyncApi getLoadBalancerApi();
+
+    @Delegate
+    PublicIPAddressAsyncApi getPublicIPAddressApi();
+}
diff --git a/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/FGCPProviderMetadata.java b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/FGCPProviderMetadata.java
new file mode 100644
index 0000000..a7718d4
--- /dev/null
+++ b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/FGCPProviderMetadata.java
@@ -0,0 +1,57 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.fujitsu.fgcp;
+
+import static org.jclouds.compute.config.ComputeServiceProperties.TEMPLATE;
+
+import java.util.Properties;
+
+import org.jclouds.providers.internal.BaseProviderMetadata;
+
+/**
+ * Base implementation of {@link org.jclouds.providers.ProviderMetadata} for
+ * FGCP.
+ * 
+ * @author Dies Koper
+ */
+public class FGCPProviderMetadata extends BaseProviderMetadata {
+
+    private static final long serialVersionUID = 7527265705102650456L;
+
+    public static Builder builder() {
+        return new Builder();
+    }
+
+    public FGCPProviderMetadata() {
+        super(builder());
+    }
+
+    public FGCPProviderMetadata(Builder builder) {
+        super(builder);
+    }
+
+    public static Properties defaultProperties() {
+        Properties properties = new Properties();
+
+        properties.setProperty(TEMPLATE,
+                "osFamily=CENTOS,osVersionMatches=6.2,os64Bit=true");
+
+        return properties;
+    }
+}
\ No newline at end of file
diff --git a/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/binders/BindAlsoToSystemId.java b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/binders/BindAlsoToSystemId.java
new file mode 100644
index 0000000..0986997
--- /dev/null
+++ b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/binders/BindAlsoToSystemId.java
@@ -0,0 +1,70 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.fujitsu.fgcp.binders;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import javax.inject.Singleton;
+
+import org.jclouds.http.HttpRequest;
+import org.jclouds.http.HttpRequest.Builder;
+import org.jclouds.rest.Binder;
+
+/**
+ * Adds system id to resource id and binds them to query parameters
+ * 
+ * @author Dies Koper
+ */
+@Singleton
+public class BindAlsoToSystemId implements Binder {
+
+    /**
+     * 
+     * @param request
+     *            request where the query params will be set
+     * @param input
+     *            array of String params
+     */
+    @SuppressWarnings("unchecked")
+    @Override
+    public <R extends HttpRequest> R bindToRequest(R request, Object input) {
+
+        checkNotNull(input);
+        checkArgument(
+                input instanceof String,
+                "this binder only applies to String arguments: "
+                        + input.getClass());
+
+        Pattern pattern = Pattern.compile("^(\\w+-\\w+)\\b.*");
+        Matcher matcher = pattern.matcher((String) input);
+
+        checkArgument(matcher.find(),
+                "no valid resource id found to construct vsys id from: "
+                        + input.toString());
+
+        Builder<?> builder = request.toBuilder();
+        builder.replaceQueryParam("vsysId", matcher.group(1));
+
+        return (R) builder.build();
+    }
+}
diff --git a/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/compute/FGCPRestClientModule.java b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/compute/FGCPRestClientModule.java
new file mode 100644
index 0000000..c86abea
--- /dev/null
+++ b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/compute/FGCPRestClientModule.java
@@ -0,0 +1,375 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.fujitsu.fgcp.compute;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.security.KeyStore;
+import java.security.PrivateKey;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateFactory;
+import java.security.spec.KeySpec;
+import java.util.Calendar;
+import java.util.Collection;
+import java.util.Map;
+
+import javax.annotation.Resource;
+import javax.inject.Singleton;
+import javax.net.ssl.SSLContext;
+
+import org.jclouds.crypto.Crypto;
+import org.jclouds.crypto.Pems;
+import org.jclouds.date.TimeStamp;
+import org.jclouds.fujitsu.fgcp.FGCPApi;
+import org.jclouds.fujitsu.fgcp.FGCPAsyncApi;
+import org.jclouds.fujitsu.fgcp.handlers.FGCPRetryIfNotProxyAuthenticationFailureHandler;
+import org.jclouds.fujitsu.fgcp.http.SSLContextWithKeysSupplier;
+import org.jclouds.fujitsu.fgcp.location.SystemAndNetworkSegmentToLocationSupplier;
+import org.jclouds.fujitsu.fgcp.services.AdditionalDiskApi;
+import org.jclouds.fujitsu.fgcp.services.AdditionalDiskAsyncApi;
+import org.jclouds.fujitsu.fgcp.services.BuiltinServerApi;
+import org.jclouds.fujitsu.fgcp.services.BuiltinServerAsyncApi;
+import org.jclouds.fujitsu.fgcp.services.DiskImageApi;
+import org.jclouds.fujitsu.fgcp.services.DiskImageAsyncApi;
+import org.jclouds.fujitsu.fgcp.services.FirewallApi;
+import org.jclouds.fujitsu.fgcp.services.FirewallAsyncApi;
+import org.jclouds.fujitsu.fgcp.services.LoadBalancerApi;
+import org.jclouds.fujitsu.fgcp.services.LoadBalancerAsyncApi;
+import org.jclouds.fujitsu.fgcp.services.PublicIPAddressApi;
+import org.jclouds.fujitsu.fgcp.services.PublicIPAddressAsyncApi;
+import org.jclouds.fujitsu.fgcp.services.SystemTemplateApi;
+import org.jclouds.fujitsu.fgcp.services.SystemTemplateAsyncApi;
+import org.jclouds.fujitsu.fgcp.services.VirtualDCApi;
+import org.jclouds.fujitsu.fgcp.services.VirtualDCAsyncApi;
+import org.jclouds.fujitsu.fgcp.services.VirtualServerApi;
+import org.jclouds.fujitsu.fgcp.services.VirtualServerAsyncApi;
+import org.jclouds.fujitsu.fgcp.services.VirtualSystemApi;
+import org.jclouds.fujitsu.fgcp.services.VirtualSystemAsyncApi;
+import org.jclouds.fujitsu.fgcp.xml.FGCPJAXBParser;
+import org.jclouds.http.HttpRetryHandler;
+import org.jclouds.http.annotation.ClientError;
+import org.jclouds.io.InputSuppliers;
+import org.jclouds.location.suppliers.ImplicitLocationSupplier;
+import org.jclouds.location.suppliers.LocationsSupplier;
+import org.jclouds.location.suppliers.implicit.FirstNetwork;
+import org.jclouds.logging.Logger;
+import org.jclouds.rest.AuthorizationException;
+import org.jclouds.rest.ConfiguresRestClient;
+import org.jclouds.rest.annotations.Credential;
+import org.jclouds.rest.annotations.Identity;
+import org.jclouds.rest.config.RestClientModule;
+import org.jclouds.xml.XMLParser;
+
+import com.google.common.base.Supplier;
+import com.google.common.collect.ImmutableMap;
+import com.google.inject.Provides;
+import com.google.inject.Scopes;
+import com.google.inject.TypeLiteral;
+
+/**
+ * Configures the FGCP connection. This module is added in FGCPContextBuilder.
+ * 
+ * @author Dies Koper
+ */
+@ConfiguresRestClient
+public class FGCPRestClientModule extends
+        RestClientModule<FGCPApi, FGCPAsyncApi> {
+
+    @Resource
+    Logger logger = Logger.NULL;
+
+    public static final Map<Class<?>, Class<?>> DELEGATE_MAP = ImmutableMap
+            .<Class<?>, Class<?>> builder()
+            //
+            .put(VirtualDCApi.class, VirtualDCAsyncApi.class)
+            .put(VirtualSystemApi.class, VirtualSystemAsyncApi.class)
+            .put(VirtualServerApi.class, VirtualServerAsyncApi.class)
+            .put(AdditionalDiskApi.class, AdditionalDiskAsyncApi.class)
+            .put(SystemTemplateApi.class, SystemTemplateAsyncApi.class)
+            .put(DiskImageApi.class, DiskImageAsyncApi.class)
+            .put(BuiltinServerApi.class, BuiltinServerAsyncApi.class)
+            .put(FirewallApi.class, FirewallAsyncApi.class)
+            .put(LoadBalancerApi.class, LoadBalancerAsyncApi.class)
+            .put(PublicIPAddressApi.class, PublicIPAddressAsyncApi.class)
+            .build();
+
+    public FGCPRestClientModule() {
+        super(DELEGATE_MAP);
+    }
+
+    @Override
+    protected void bindErrorHandlers() {
+        // bind(HttpErrorHandler.class).annotatedWith(Redirection.class).to(ParseAWSErrorFromXmlContent.class);
+        // bind(HttpErrorHandler.class).annotatedWith(ClientError.class).to(ParseAWSErrorFromXmlContent.class);
+        // bind(HttpErrorHandler.class).annotatedWith(ServerError.class).to(ParseAWSErrorFromXmlContent.class);
+    }
+
+    @Override
+    protected void installLocations() {
+        super.installLocations();
+        bind(ImplicitLocationSupplier.class).to(FirstNetwork.class).in(
+                Scopes.SINGLETON);
+        bind(LocationsSupplier.class).to(
+                SystemAndNetworkSegmentToLocationSupplier.class).in(
+                Scopes.SINGLETON);
+    }
+
+    @Override
+    protected void bindRetryHandlers() {
+        bind(HttpRetryHandler.class).annotatedWith(ClientError.class).to(
+                FGCPRetryIfNotProxyAuthenticationFailureHandler.class);
+    }
+
+    @Override
+    protected void configure() {
+        super.configure();
+        bind(XMLParser.class).to(FGCPJAXBParser.class);
+        bind(new TypeLiteral<Supplier<SSLContext>>() {
+        }).to(new TypeLiteral<SSLContextWithKeysSupplier>() {
+        });
+    }
+
+    @Provides
+    @TimeStamp
+    protected Calendar provideCalendar() {
+        return Calendar.getInstance();
+    }
+
+    /*
+     * 
+     * @Provides
+     * 
+     * @Singleton protected KeyStore
+     * provideKeyStore(@Named(Constants.PROPERTY_IDENTITY) String
+     * keyStoreFilename, @Named(Constants.PROPERTY_CREDENTIAL) String
+     * keyStorePassword) throws KeyStoreException { KeyStore keyStore =
+     * KeyStore.getInstance("pkcs12");
+     * 
+     * try { FileInputStream is = new
+     * FileInputStream(checkNotNull(keyStoreFilename,
+     * Constants.PROPERTY_IDENTITY)); keyStore.load(is,
+     * checkNotNull(keyStorePassword,
+     * Constants.PROPERTY_CREDENTIAL).toCharArray()); } catch (Exception e) { //
+     * expecting IOException, NoSuchAlgorithmException, CertificateException
+     * logger.error(e, "Keystore could not be opened: %s", keyStoreFilename); }
+     * return keyStore; }
+     * 
+     * @Provides
+     * 
+     * @Singleton protected PrivateKey provideKey(Provider<KeyStore>
+     * keyStoreProvider, @Named(Constants.PROPERTY_CREDENTIAL) String
+     * keyPassword) throws KeyStoreException, NoSuchAlgorithmException,
+     * UnrecoverableKeyException { KeyStore keyStore = keyStoreProvider.get();
+     * if (keyStore == null) return null;
+     * 
+     * // retrieving 1st alias in keystore as expecting only one String alias =
+     * checkNotNull(keyStore.aliases().nextElement(),
+     * "first alias in keystore"); return (PrivateKey) keyStore.getKey(alias,
+     * checkNotNull(keyPassword, Constants.PROPERTY_CREDENTIAL).toCharArray());
+     * }
+     */
+    /*
+     * maybe we can provide two authentication methods:
+     * 
+     * 1. same as DeltaCloud: User passes a folder name as identity and cert
+     * password as credential Note: pass relative path (e.g. cert's path:
+     * c:\jclouds\certs\dkoper\UserCert.p12: user passes 'dkoper': provider
+     * impl. finds it under e.g. $USER_DIR or $CURRENT_DIR or pass absolute path
+     * 2. no file access for GAE: User passes cert in PEM format (converted from
+     * UserCert.p12 using openssl?) as identity and cert password as credential
+     */
+    @Provides
+    @Singleton
+    protected KeyStore provideKeyStore(Crypto crypto, @Identity String cert,
+            @Credential String keyStorePassword) {
+        KeyStore keyStore = null;
+        try {
+            keyStore = KeyStore.getInstance("PKCS12");
+
+            // System.out.println("cert: " + cert);
+            // System.out.println("pwd : " + keyStorePassword);
+            File certFile = new File(checkNotNull(cert));
+            if (certFile.isFile()) { // cert is path to pkcs12 file
+
+                keyStore.load(new FileInputStream(certFile),
+                        keyStorePassword.toCharArray());
+            } else { // cert is PEM encoded, containing private key and certs
+
+                // System.out.println("cert:\n" + cert);
+                // split in private key and certs
+                int privateKeyBeginIdx = cert.indexOf("-----BEGIN PRIVATE KEY");
+                int privateKeyEndIdx = cert.indexOf("-----END PRIVATE KEY");
+                String pemPrivateKey = cert.substring(privateKeyBeginIdx,
+                        privateKeyEndIdx + 26);
+                // System.out.println("***************");
+                // System.out.println("pemPrivateKey:\n" + pemPrivateKey);
+                // System.out.println("***************");
+
+                String pemCerts = "";
+                int certsBeginIdx = 0;
+
+                do {
+                    certsBeginIdx = cert.indexOf("-----BEGIN CERTIFICATE",
+                            certsBeginIdx);
+                    // System.out.println("begin:" + certsBeginIdx);
+
+                    if (certsBeginIdx >= 0) {
+                        int certsEndIdx = cert.indexOf("-----END CERTIFICATE",
+                                certsBeginIdx) + 26;
+                        // System.out.println("end  :" + certsEndIdx);
+                        pemCerts += cert.substring(certsBeginIdx, certsEndIdx);
+                        certsBeginIdx = certsEndIdx;
+                    }
+                } while (certsBeginIdx != -1);
+                // System.out.println("***************");
+                // System.out.println("pemCerts:\n" + pemCerts);
+                // System.out.println("***************");
+
+                /*
+                 * String pemCerts = "-----BEGIN "; Splitter pemSplitter =
+                 * Splitter.on("-----BEGIN ");
+                 * 
+                 * for (String part : pemSplitter.split(cert)) {
+                 * System.out.println("***************");
+                 * System.out.println("Part:\n" + part);
+                 * System.out.println("***************");
+                 * 
+                 * if (part.startsWith("PRIVATE KEY")
+                 */
+                /* || part.startsWith("RSA PRIVATE KEY)" *//*
+                                                            * ) {
+                                                            * 
+                                                            * int certEndIdx =
+                                                            * part.lastIndexOf
+                                                            * ("-----END");
+                                                            * pemPrivateKey +=
+                                                            * part.substring(0,
+                                                            * certEndIdx + 26);
+                                                            * // take up to next
+                                                            * "-----" (i.e.
+                                                            * "-----END") //
+                                                            * Splitter
+                                                            * keySplitter =
+                                                            * Splitter
+                                                            * .on("-----").
+                                                            * omitEmptyStrings
+                                                            * ().trimResults();
+                                                            * //
+                                                            * Iterator<String>
+                                                            * iter =
+                                                            * keySplitter.
+                                                            * split(part
+                                                            * ).iterator(); //
+                                                            * String keyName =
+                                                            * iter.next() +
+                                                            * "-----\n"; //
+                                                            * pemPrivateKey +=
+                                                            * keyName; ////
+                                                            * System.out
+                                                            * .println
+                                                            * ("Skipping: '" +
+                                                            * iter.next() +
+                                                            * "'"); //
+                                                            * pemPrivateKey +=
+                                                            * iter.next(); //
+                                                            * pemPrivateKey +=
+                                                            * "\n-----END " +
+                                                            * keyName;
+                                                            * System.out.println
+                                                            * (
+                                                            * "/////////////////"
+                                                            * );
+                                                            * System.out.println
+                                                            * (
+                                                            * "pemPrivateKey:\n"
+                                                            * + pemPrivateKey);
+                                                            * System
+                                                            * .out.println(
+                                                            * "/////////////////"
+                                                            * ); } else if
+                                                            * (part.startsWith
+                                                            * ("CERTIFICATE")) {
+                                                            * 
+                                                            * // take up to next
+                                                            * "-----" (i.e.
+                                                            * "-----END") // or
+                                                            * take up to last
+                                                            * END CERTIFICATE?
+                                                            * int certEndIdx =
+                                                            * part.lastIndexOf (
+                                                            * "----- END CERTIFICATE"
+                                                            * ); // pemCerts +=
+                                                            * part. // Splitter
+                                                            * keySplitter =
+                                                            * Splitter
+                                                            * .on("-----").
+                                                            * omitEmptyStrings
+                                                            * (); // pemCerts +=
+                                                            * keySplitter
+                                                            * .split(part)
+                                                            * .iterator
+                                                            * ().next(); //
+                                                            * pemCerts +=
+                                                            * "-----BEGIN "; }
+                                                            * else { // ignore
+                                                            * the fluff in
+                                                            * between (Bag
+                                                            * Attributes, etc.)
+                                                            * } }
+                                                            */
+
+                // parse private key
+                KeySpec keySpec = Pems.privateKeySpec(InputSuppliers
+                        .of(pemPrivateKey));
+                PrivateKey privateKey = crypto.rsaKeyFactory().generatePrivate(
+                        keySpec);
+
+                // populate keystore with private key and certs
+                CertificateFactory cf = CertificateFactory.getInstance("X.509");
+                @SuppressWarnings("unchecked")
+                Collection<Certificate> certs = (Collection<Certificate>) cf
+                        .generateCertificates(new ByteArrayInputStream(pemCerts
+                                .getBytes("UTF-8")));
+                keyStore.load(null);
+                keyStore.setKeyEntry("dummy", privateKey,
+                        keyStorePassword.toCharArray(),
+                        certs.toArray(new java.security.cert.Certificate[0]));
+
+                // System.out.println("private key: " + privateKey.getFormat() +
+                // "; "
+                // + privateKey.getAlgorithm() + "; class: " +
+                // privateKey.getClass().getName());// + "; " + new
+                // String(privateKey.getEncoded()));
+
+            }
+        } catch (Exception e) {
+            /*
+             * KeyStoreException, IOException, NoSuchAlgorithmException,
+             * CertificateException, InvalidKeySpecException
+             */
+            throw new AuthorizationException("Error loading certificate", e);
+        }
+
+        return keyStore;
+    }
+
+}
diff --git a/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/compute/config/FGCPComputeServiceContextModule.java b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/compute/config/FGCPComputeServiceContextModule.java
new file mode 100644
index 0000000..46f3646
--- /dev/null
+++ b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/compute/config/FGCPComputeServiceContextModule.java
@@ -0,0 +1,140 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.fujitsu.fgcp.compute.config;
+
+import org.jclouds.compute.ComputeServiceAdapter;
+import org.jclouds.compute.config.ComputeServiceAdapterContextModule;
+import org.jclouds.compute.domain.Hardware;
+import org.jclouds.compute.domain.Image;
+import org.jclouds.compute.domain.NodeMetadata;
+import org.jclouds.compute.domain.OperatingSystem;
+import org.jclouds.compute.domain.Processor;
+import org.jclouds.compute.domain.Volume;
+import org.jclouds.compute.options.TemplateOptions;
+import org.jclouds.domain.Location;
+import org.jclouds.fujitsu.fgcp.compute.functions.CPUToProcessor;
+import org.jclouds.fujitsu.fgcp.compute.functions.DiskImageToImage;
+import org.jclouds.fujitsu.fgcp.compute.functions.DiskImageToOperatingSystem;
+import org.jclouds.fujitsu.fgcp.compute.functions.DiskToVolume;
+import org.jclouds.fujitsu.fgcp.compute.functions.ServerTypeToHardware;
+import org.jclouds.fujitsu.fgcp.compute.functions.VServerMetadataToNodeMetadata;
+import org.jclouds.fujitsu.fgcp.compute.options.FGCPTemplateOptions;
+import org.jclouds.fujitsu.fgcp.compute.strategy.FGCPComputeServiceAdapter;
+import org.jclouds.fujitsu.fgcp.compute.strategy.VServerMetadata;
+import org.jclouds.fujitsu.fgcp.domain.CPU;
+import org.jclouds.fujitsu.fgcp.domain.Disk;
+import org.jclouds.fujitsu.fgcp.domain.DiskImage;
+import org.jclouds.fujitsu.fgcp.domain.ServerType;
+import org.jclouds.functions.IdentityFunction;
+
+import com.google.common.base.Function;
+import com.google.inject.TypeLiteral;
+//import org.jclouds.fujitsu.fgcp.compute.predicates.ServerStopped;
+
+/**
+ * Added in FGCPContextBuilder
+ * 
+ * @author Dies Koper
+ */
+public class FGCPComputeServiceContextModule
+        extends
+        ComputeServiceAdapterContextModule<VServerMetadata, ServerType, DiskImage, Location> {
+
+    @SuppressWarnings({ "unchecked", "rawtypes" })
+    @Override
+    protected void configure() {
+        super.configure();
+        // installDependencies();
+
+        bind(
+                new TypeLiteral<ComputeServiceAdapter<VServerMetadata, ServerType, DiskImage, Location>>() {
+                }).to(FGCPComputeServiceAdapter.class);
+
+        // the following bind functions that map FGCP domain specific resources
+        // to jclouds'
+        bind(new TypeLiteral<Function<VServerMetadata, NodeMetadata>>() {
+        }).to(VServerMetadataToNodeMetadata.class);
+        bind(new TypeLiteral<Function<DiskImage, Image>>() {
+        }).to(DiskImageToImage.class);
+        bind(new TypeLiteral<Function<DiskImage, OperatingSystem>>() {
+        }).to(DiskImageToOperatingSystem.class);
+        bind(new TypeLiteral<Function<ServerType, Hardware>>() {
+        }).to(ServerTypeToHardware.class);
+        bind(new TypeLiteral<Function<Disk, Volume>>() {
+        }).to(DiskToVolume.class);
+        bind(new TypeLiteral<Function<CPU, Processor>>() {
+        }).to(CPUToProcessor.class);
+
+        // we aren't converting hardware from a provider-specific type
+        bind(new TypeLiteral<Function<Location, Location>>() {
+        }).to((Class) IdentityFunction.class);
+        bind(new TypeLiteral<Function<Hardware, Hardware>>() {
+        }).to((Class) IdentityFunction.class);
+
+        bind(TemplateOptions.class).to(FGCPTemplateOptions.class);
+
+
+        // bind(new TypeLiteral<Predicate<String>>() {
+        // }).to((Class) ServerStopped.class);
+
+        // need to look into the following later for to map (create) jclouds'
+        // location to FGCP.
+        // see LocationScope:
+        // PROVIDER: FGCP
+        // REGION: country?/country+state?
+        // ZONE: virtual DC: contractId
+        // NETWORK: VSYS? DMZ/SECURE1/SECURE2?
+        // RACK: N/A?
+        // HOST: N/A?
+        // there are no locations except the provider
+        // bind(new TypeLiteral<Supplier<Location>>() {
+        // }).to(OnlyLocationOrFirstZone.class);
+
+        // install(new FGCPBindComputeStrategiesByClass());
+        // install(new FGCPBindComputeSuppliersByClass());
+        // bind(ReviseParsedImage.class).to(AWSEC2ReviseParsedImage.class);
+        // bind(CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions.class).to(
+        // CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions.class);
+        // bind(EC2HardwareSupplier.class).to(AWSEC2HardwareSupplier.class);
+        // bind(EC2TemplateBuilderImpl.class).to(AWSEC2TemplateBuilderImpl.class);
+        // bind(EC2GetNodeMetadataStrategy.class).to(AWSEC2GetNodeMetadataStrategy.class);
+        // bind(InstancePresent.class).to(AWSEC2InstancePresent.class);
+        // bind(EC2CreateNodesInGroupThenAddToSet.class).to(AWSEC2CreateNodesInGroupThenAddToSet.class);
+        // bind(RunningInstanceToNodeMetadata.class).to(AWSRunningInstanceToNodeMetadata.class);
+    }
+
+    // @Provides
+    // @Singleton
+    // @Named("SECURITY")
+    // protected Predicate<String> provideServerStopped(ServerStopped
+    // serverStopped, Timeouts timeouts) {
+    // return new RetryablePredicate<String>(serverStopped,
+    // timeouts.nodeSuspended);
+    // }
+
+    protected void installDependencies() {
+        // install(new FGCPComputeServiceDependenciesModule());
+    }
+
+    /*
+     * @Override protected TemplateBuilder provideTemplate(Injector injector,
+     * TemplateBuilder template) { return
+     * template.osFamily(CENTOS).os64Bit(true); }
+     */
+}
diff --git a/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/compute/functions/CPUToProcessor.java b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/compute/functions/CPUToProcessor.java
new file mode 100644
index 0000000..a26508e
--- /dev/null
+++ b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/compute/functions/CPUToProcessor.java
@@ -0,0 +1,44 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.fujitsu.fgcp.compute.functions;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import com.google.common.base.Function;
+import org.jclouds.compute.domain.Processor;
+import org.jclouds.fujitsu.fgcp.domain.CPU;
+
+import javax.inject.Singleton;
+
+/**
+ * Created by IntelliJ IDEA.
+ * 
+ * @author Dies Koper
+ */
+@Singleton
+public class CPUToProcessor implements Function<CPU, Processor> {
+
+    @Override
+    public Processor apply(CPU cpu) {
+        checkNotNull(cpu, "cpu");
+
+        return new Processor(Double.valueOf(cpu.getCores()), Double.valueOf(cpu
+                .getSpeedPerCore()));
+    }
+}
diff --git a/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/compute/functions/DiskImageToImage.java b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/compute/functions/DiskImageToImage.java
new file mode 100644
index 0000000..e5200da
--- /dev/null
+++ b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/compute/functions/DiskImageToImage.java
@@ -0,0 +1,80 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.fujitsu.fgcp.compute.functions;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+import org.jclouds.compute.domain.Image;
+import org.jclouds.compute.domain.Image.Status;
+import org.jclouds.compute.domain.ImageBuilder;
+import org.jclouds.compute.domain.OperatingSystem;
+import org.jclouds.compute.domain.OsFamily;
+import org.jclouds.domain.LoginCredentials;
+import org.jclouds.fujitsu.fgcp.domain.DiskImage;
+import org.jclouds.location.suppliers.all.RegionToProviderOrJustProvider;
+
+import com.google.common.base.Function;
+import com.google.common.collect.Iterables;
+
+/**
+ * Created by IntelliJ IDEA.
+ * 
+ * @author Dies Koper
+ */
+@Singleton
+public class DiskImageToImage implements Function<DiskImage, Image> {
+
+    private final DiskImageToOperatingSystem diskImageToOperatingSystem;
+    private final RegionToProviderOrJustProvider regionSupplier;
+
+    @Inject
+    public DiskImageToImage(
+            DiskImageToOperatingSystem diskImageToOperatingSystem,
+            RegionToProviderOrJustProvider locationSupplier) {
+        this.diskImageToOperatingSystem = checkNotNull(
+                diskImageToOperatingSystem, "diskImageToOperatingSystem");
+        this.regionSupplier = checkNotNull(locationSupplier, "locationProvider");
+    }
+
+    @Override
+    public Image apply(DiskImage from) {
+        checkNotNull(from, "disk image");
+
+        ImageBuilder builder = new ImageBuilder();
+
+        builder.ids(from.getId());
+        builder.name(from.getName());
+        builder.description(from.getDescription());
+        builder.location(Iterables.getOnlyElement(regionSupplier.get()));
+        // in fgcp, if the image is listed it is available
+        builder.status(Status.AVAILABLE);
+
+        OperatingSystem os = diskImageToOperatingSystem.apply(from);
+        builder.operatingSystem(os);
+        String user = os.getFamily() == OsFamily.WINDOWS ? "Administrator"
+                : "root";
+        builder.defaultCredentials(LoginCredentials.builder().identity(user)
+                .noPassword().build());
+
+        return builder.build();
+    }
+}
diff --git a/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/compute/functions/DiskImageToOperatingSystem.java b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/compute/functions/DiskImageToOperatingSystem.java
new file mode 100644
index 0000000..b1ce9a1
--- /dev/null
+++ b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/compute/functions/DiskImageToOperatingSystem.java
@@ -0,0 +1,73 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.fujitsu.fgcp.compute.functions;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import javax.inject.Singleton;
+
+import org.jclouds.compute.domain.OperatingSystem;
+import org.jclouds.compute.domain.OsFamily;
+import org.jclouds.compute.util.ComputeServiceUtils;
+import org.jclouds.fujitsu.fgcp.domain.DiskImage;
+
+import com.google.common.base.Function;
+
+/**
+ * 
+ * @author Dies Koper
+ */
+@Singleton
+public class DiskImageToOperatingSystem implements
+        Function<DiskImage, OperatingSystem> {
+
+    private static final Pattern OS_VERSION_PATTERN = Pattern
+            .compile("^.*?(\\d.*)\\s(32|64).*$");
+
+    @Override
+    public OperatingSystem apply(DiskImage image) {
+        checkNotNull(image, "disk image");
+
+        // convert to short name rhel to accommodate ComputeServiceUtils
+        // conventions
+        String shortOsName = image.getOsName().replace(
+                "Red Hat Enterprise Linux", "rhel");
+        OsFamily osFamily = ComputeServiceUtils
+                .parseOsFamilyOrUnrecognized(shortOsName);
+        OperatingSystem.Builder builder = OperatingSystem.builder();
+
+        builder.name(image.getOsName());
+        builder.family(osFamily);
+        builder.is64Bit(image.getOsName().contains("64bit")
+                || image.getOsName().contains("64 bit")
+                || image.getOsName().contains("x64"));
+        // OsType returns guest type (hvm, pv), which aws-ec2 is mapping to arch
+        builder.arch(image.getOsType());
+        Matcher m = OS_VERSION_PATTERN.matcher(image.getOsName());
+        if (m.matches()) {
+            builder.version(m.group(1));
+        }
+        builder.description(image.getOsName());
+
+        return builder.build();
+    }
+}
diff --git a/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/compute/functions/DiskToVolume.java b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/compute/functions/DiskToVolume.java
new file mode 100644
index 0000000..c9f4067
--- /dev/null
+++ b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/compute/functions/DiskToVolume.java
@@ -0,0 +1,53 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.fujitsu.fgcp.compute.functions;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import com.google.common.base.Function;
+import org.jclouds.compute.domain.Volume;
+import org.jclouds.compute.domain.VolumeBuilder;
+import org.jclouds.fujitsu.fgcp.domain.Disk;
+
+import javax.inject.Singleton;
+
+/**
+ * Created by IntelliJ IDEA.
+ * 
+ * @author Dies Koper
+ */
+@Singleton
+public class DiskToVolume implements Function<Disk, Volume> {
+
+    @Override
+    public Volume apply(Disk disk) {
+        checkNotNull(disk, "disk");
+
+        VolumeBuilder builder = new VolumeBuilder();
+
+        builder.size(1000f * Float.valueOf(disk.getSize()));
+        // "Disk"'s are additional disks; they can't be booted disk(?)
+        builder.bootDevice(false);
+        builder.durable(true);
+        builder.type(Volume.Type.SAN);
+        builder.id("type: " + disk.getType() + " usage: " + disk.getUsage());
+
+        return builder.build();
+    }
+}
diff --git a/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/compute/functions/ResourceIdToFirewallId.java b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/compute/functions/ResourceIdToFirewallId.java
new file mode 100644
index 0000000..2e91f2b
--- /dev/null
+++ b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/compute/functions/ResourceIdToFirewallId.java
@@ -0,0 +1,51 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.fujitsu.fgcp.compute.functions;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+import com.google.common.base.Function;
+
+/**
+ * Determines the id of the firewall associated with a virtual system, server,
+ * load balancer or disk.
+ * 
+ * @author Dies Koper
+ */
+@Singleton
+public class ResourceIdToFirewallId implements Function<String, String> {
+
+    private ResourceIdToSystemId toSystemId;
+
+    @Inject
+    private ResourceIdToFirewallId(ResourceIdToSystemId resourceIdToSystemId) {
+        this.toSystemId = checkNotNull(resourceIdToSystemId,
+                "resourceIdToSystemId");
+    }
+
+    @Override
+    public String apply(String id) {
+        checkNotNull(id, "resource id");
+
+        return toSystemId.apply(id) + "-S-0001";
+    }
+}
diff --git a/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/compute/functions/ResourceIdToSystemId.java b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/compute/functions/ResourceIdToSystemId.java
new file mode 100644
index 0000000..01b1891
--- /dev/null
+++ b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/compute/functions/ResourceIdToSystemId.java
@@ -0,0 +1,52 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.fujitsu.fgcp.compute.functions;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import javax.inject.Singleton;
+
+import com.google.common.base.Function;
+
+/**
+ * Determines the id of the virtual system that a server, load balancer or disk
+ * is part of.
+ * 
+ * @author Dies Koper
+ */
+@Singleton
+public class ResourceIdToSystemId implements Function<String, String> {
+
+    @Override
+    public String apply(String id) {
+        checkNotNull(id, "resource id");
+
+        Pattern pattern = Pattern.compile("^(\\w+-\\w+)\\b.*");
+        Matcher matcher = pattern.matcher((String) id);
+
+        checkArgument(matcher.find(),
+                "no valid resource id found: " + id.toString());
+
+        return matcher.group(1);
+    }
+}
diff --git a/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/compute/functions/ServerTypeToHardware.java b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/compute/functions/ServerTypeToHardware.java
new file mode 100644
index 0000000..ec99cf5
--- /dev/null
+++ b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/compute/functions/ServerTypeToHardware.java
@@ -0,0 +1,68 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.fujitsu.fgcp.compute.functions;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+import org.jclouds.compute.domain.Hardware;
+import org.jclouds.compute.domain.HardwareBuilder;
+import org.jclouds.compute.domain.Image;
+import org.jclouds.fujitsu.fgcp.domain.ServerType;
+
+import com.google.common.base.Function;
+import com.google.common.base.Predicates;
+import com.google.common.collect.Iterables;
+
+/**
+ * Created by IntelliJ IDEA.
+ * 
+ * @author Dies Koper
+ */
+@Singleton
+public class ServerTypeToHardware implements Function<ServerType, Hardware> {
+    private final CPUToProcessor cpuToProcessor;
+    private final DiskToVolume diskToVolume;
+
+    @Inject
+    public ServerTypeToHardware(CPUToProcessor cpuToProcessor,
+            DiskToVolume diskToVolume) {
+        this.cpuToProcessor = checkNotNull(cpuToProcessor);
+        this.diskToVolume = checkNotNull(diskToVolume);
+    }
+
+    @Override
+    public Hardware apply(ServerType from) {
+        checkNotNull(from, "ServerType");
+        HardwareBuilder builder = new HardwareBuilder();
+
+        builder.ids(from.getId());
+        builder.name(from.getName());
+        builder.ram((int) (1000d * Double.valueOf(from.getMemory().getSize())));
+        builder.processor(cpuToProcessor.apply(from.getCpu()));
+        builder.supportsImage(Predicates.<Image> alwaysTrue());
+        // all servers are 64bit. The OS however may be 32 bit.
+        builder.is64Bit(true);
+        builder.volumes(Iterables.transform(from.getDisks(), diskToVolume));
+
+        return builder.build();
+    }
+}
diff --git a/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/compute/functions/SingleElementResponseToElement.java b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/compute/functions/SingleElementResponseToElement.java
new file mode 100644
index 0000000..b8677a4
--- /dev/null
+++ b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/compute/functions/SingleElementResponseToElement.java
@@ -0,0 +1,34 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.fujitsu.fgcp.compute.functions;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import org.jclouds.fujitsu.fgcp.xml.internal.SingleElementResponse;
+
+import com.google.common.base.Function;
+
+public class SingleElementResponseToElement implements
+        Function<SingleElementResponse, Object> {
+
+    @Override
+    public Object apply(SingleElementResponse r) {
+        return checkNotNull(r, "response").getElement();
+    }
+}
diff --git a/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/compute/functions/VServerMetadataToNodeMetadata.java b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/compute/functions/VServerMetadataToNodeMetadata.java
new file mode 100644
index 0000000..66c390b
--- /dev/null
+++ b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/compute/functions/VServerMetadataToNodeMetadata.java
@@ -0,0 +1,245 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.fujitsu.fgcp.compute.functions;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.NoSuchElementException;
+import java.util.Set;
+
+import javax.annotation.Resource;
+import javax.inject.Inject;
+import javax.inject.Named;
+import javax.inject.Singleton;
+
+import org.jclouds.collect.Memoized;
+import org.jclouds.compute.domain.Hardware;
+import org.jclouds.compute.domain.Image;
+import org.jclouds.compute.domain.NodeMetadata;
+import org.jclouds.compute.domain.NodeMetadata.Status;
+import org.jclouds.compute.domain.NodeMetadataBuilder;
+import org.jclouds.compute.functions.GroupNamingConvention;
+import org.jclouds.compute.reference.ComputeServiceConstants;
+import org.jclouds.domain.Location;
+import org.jclouds.domain.LoginCredentials;
+import org.jclouds.fujitsu.fgcp.compute.strategy.VServerMetadata;
+import org.jclouds.fujitsu.fgcp.domain.VServer;
+import org.jclouds.fujitsu.fgcp.domain.VServerStatus;
+import org.jclouds.fujitsu.fgcp.domain.VServerWithVNICs;
+import org.jclouds.logging.Logger;
+
+import com.google.common.base.Function;
+import com.google.common.base.Predicate;
+import com.google.common.base.Supplier;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Iterables;
+
+/**
+ * @author Dies Koper
+ */
+@Singleton
+public class VServerMetadataToNodeMetadata implements
+        Function<VServerMetadata, NodeMetadata> {
+
+    public static final Map<VServerStatus, Status> vServerToStatus = ImmutableMap
+            .<VServerStatus, Status> builder()
+            .put(VServerStatus.DEPLOYING, Status.PENDING)
+            .put(VServerStatus.RUNNING, Status.RUNNING)
+            .put(VServerStatus.STOPPING, Status.PENDING)
+            .put(VServerStatus.STOPPED, Status.SUSPENDED)
+            .put(VServerStatus.STARTING, Status.PENDING)
+            .put(VServerStatus.FAILOVER, Status.RUNNING)
+            .put(VServerStatus.UNEXPECTED_STOP, Status.SUSPENDED)
+            .put(VServerStatus.RESTORING, Status.PENDING)
+            .put(VServerStatus.BACKUP_ING, Status.PENDING)
+            .put(VServerStatus.ERROR, Status.ERROR)
+            .put(VServerStatus.START_ERROR, Status.ERROR)
+            .put(VServerStatus.STOP_ERROR, Status.ERROR)
+            .put(VServerStatus.CHANGE_TYPE, Status.PENDING)
+            .put(VServerStatus.REGISTERING, Status.PENDING)
+            .put(VServerStatus.UNRECOGNIZED, Status.UNRECOGNIZED).build();
+
+    @Resource
+    @Named(ComputeServiceConstants.COMPUTE_LOGGER)
+    protected Logger logger = Logger.NULL;
+
+    protected final Supplier<Set<? extends Location>> locations;
+    protected final Supplier<Set<? extends Image>> images;
+    protected final Supplier<Set<? extends Hardware>> hardwares;
+    protected final GroupNamingConvention nodeNamingConvention;
+
+    private static class FindImageForVServer implements Predicate<Image> {
+        private final VServer server;
+
+        private FindImageForVServer(VServer server) {
+            this.server = server;
+        }
+
+        @Override
+        public boolean apply(Image input) {
+            return input.getId().equals(server.getDiskimageId());
+        }
+    }
+
+    protected Image parseImage(VServer from) {
+        try {
+            return Iterables.find(images.get(), new FindImageForVServer(from));
+        } catch (NoSuchElementException e) {
+            logger.warn("could not find a matching image for server %s", from);
+        }
+        return null;
+    }
+
+    private static class FindHardwareForServerType implements
+            Predicate<Hardware> {
+        private final String type;
+
+        private FindHardwareForServerType(String type) {
+            this.type = type;
+        }
+
+        @Override
+        public boolean apply(Hardware input) {
+            return input.getName().equals(type);
+        }
+    }
+
+    protected Hardware parseHardware(String from) {
+        try {
+            return Iterables.find(hardwares.get(),
+                    new FindHardwareForServerType(from));
+        } catch (NoSuchElementException e) {
+            logger.warn(
+                    "could not find a matching hardware for server type %s",
+                    from);
+        }
+        return null;
+    }
+
+    private static class FindLocationForVServer implements Predicate<Location> {
+        private final VServerWithVNICs server;
+
+        private FindLocationForVServer(VServerWithVNICs server) {
+            this.server = server;
+        }
+
+        @Override
+        public boolean apply(Location input) {
+            return input.getId().equals(
+                    Iterables.getLast(server.getVnics()).getNetworkId());
+        }
+    }
+
+    protected Location parseLocation(VServerWithVNICs from) {
+        try {
+            return Iterables.find(locations.get(), new FindLocationForVServer(
+                    from));
+        } catch (NoSuchElementException e) {
+            logger.warn("could not find a matching realm for server %s", from);
+        }
+        return null;
+    }
+
+    @Inject
+    VServerMetadataToNodeMetadata(
+            @Memoized Supplier<Set<? extends Location>> locations,
+            @Memoized Supplier<Set<? extends Image>> images,
+            @Memoized Supplier<Set<? extends Hardware>> hardwares,
+            GroupNamingConvention.Factory namingConvention) {
+        this.images = checkNotNull(images, "images");
+        this.locations = checkNotNull(locations, "locations");
+        this.hardwares = checkNotNull(hardwares, "hardwares");
+        this.nodeNamingConvention = checkNotNull(namingConvention,
+                "namingConvention").createWithoutPrefix();
+    }
+
+    @Override
+    public NodeMetadata apply(VServerMetadata from) {
+        NodeMetadataBuilder builder = new NodeMetadataBuilder();
+
+        builder.ids(from.getId());
+        builder.name(from.getName());
+        builder.group(nodeNamingConvention.groupInUniqueNameOrNull(from
+                .getName()));
+        if (from.getStatus() == null)
+            System.out.println("status null for: " + from.getId() + ": "
+                    + from.getName());
+
+        builder.status(vServerToStatus.get(from.getStatus()));
+        builder.privateAddresses(ImmutableSet.<String> of());
+        builder.publicAddresses(ImmutableSet.<String> of());
+
+        //
+        // if (from.getIps() != null) {
+        //
+        // builder.publicAddresses(Collections2.transform(from.getIps(),
+        // new Function<PublicIP, String>() {
+        //
+        // @Override
+        // public String apply(PublicIP input) {
+        // return input.getAddress();
+        // }
+        //
+        // }));
+        // }
+
+        if (from.getServer() != null) {
+
+            builder.imageId(from.getServer().getDiskimageId());
+            builder.hardware(parseHardware(from.getServer().getType()));
+
+            LoginCredentials.Builder credentialsBuilder = LoginCredentials
+                    .builder().password(from.getInitialPassword());
+
+            Image image = parseImage(from.getServer());
+            // image will not be found if server was created a while back and
+            // the image has since been destroyed or discontinued (like an old
+            // CentOS version)
+            if (image != null) {
+
+                builder.operatingSystem(image.getOperatingSystem());
+                String user = image.getDefaultCredentials().getUser();
+                credentialsBuilder.identity(user);
+            }
+
+            builder.credentials(credentialsBuilder.build());
+
+            if (from.getServer() instanceof VServerWithVNICs) {
+
+                VServerWithVNICs server = (VServerWithVNICs) from.getServer();
+                builder.location(parseLocation(server));
+                List<String> ips = new ArrayList<String>();
+                if (server.getVnics() != null && server.getVnics().iterator().next().getPrivateIp() != null) {
+                    ips.add(server.getVnics().iterator().next().getPrivateIp());
+                }
+                builder.privateAddresses(ips);
+            }
+        }
+        if (from.getTemplate() != null) {
+            // when creating a new node
+            builder.location(from.getTemplate().getLocation());
+        }
+
+        return builder.build();
+    }
+}
diff --git a/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/compute/options/FGCPTemplateOptions.java b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/compute/options/FGCPTemplateOptions.java
new file mode 100644
index 0000000..ca11f6c
--- /dev/null
+++ b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/compute/options/FGCPTemplateOptions.java
@@ -0,0 +1,29 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.fujitsu.fgcp.compute.options;
+
+import org.jclouds.compute.options.TemplateOptions;
+
+/**
+ * 
+ * @author Dies Koper
+ */
+public class FGCPTemplateOptions extends TemplateOptions {
+
+}
diff --git a/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/compute/predicates/ServerStopped.java b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/compute/predicates/ServerStopped.java
new file mode 100644
index 0000000..bda281c
--- /dev/null
+++ b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/compute/predicates/ServerStopped.java
@@ -0,0 +1,63 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.fujitsu.fgcp.compute.predicates;
+
+import javax.annotation.Resource;
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+import org.jclouds.fujitsu.fgcp.FGCPApi;
+import org.jclouds.fujitsu.fgcp.domain.VServerStatus;
+import org.jclouds.logging.Logger;
+
+import com.google.common.base.Predicate;
+
+/**
+ * 
+ * @author Adrian Cole
+ * @author Dies Koper
+ * 
+ */
+@Singleton
+public class ServerStopped implements Predicate<String> {
+
+    private final FGCPApi api;
+
+    @Resource
+    protected Logger logger = Logger.NULL;
+
+    @Inject
+    public ServerStopped(FGCPApi api) {
+        this.api = api;
+    }
+
+    public boolean apply(String serverId) {
+        logger.trace("looking for status on server %s", serverId);
+
+        VServerStatus status = api.getVirtualServerApi().getStatus(serverId);
+        logger.trace("looking for status on server %s: currently: %s",
+                serverId, status);
+
+        if (status == VServerStatus.ERROR || status == VServerStatus.STOP_ERROR)
+            throw new IllegalStateException("server not around or in error: "
+                    + status);
+        return status == VServerStatus.STOPPED;
+    }
+
+}
diff --git a/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/compute/predicates/SystemStatusNormal.java b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/compute/predicates/SystemStatusNormal.java
new file mode 100644
index 0000000..8812335
--- /dev/null
+++ b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/compute/predicates/SystemStatusNormal.java
@@ -0,0 +1,62 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.fujitsu.fgcp.compute.predicates;
+
+import javax.annotation.Resource;
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+import org.jclouds.fujitsu.fgcp.FGCPApi;
+import org.jclouds.fujitsu.fgcp.domain.VServerStatus;
+import org.jclouds.fujitsu.fgcp.domain.VSystemStatus;
+import org.jclouds.logging.Logger;
+
+import com.google.common.base.Predicate;
+
+/**
+ * 
+ * @author Dies Koper
+ * 
+ */
+@Singleton
+public class SystemStatusNormal implements Predicate<String> {
+
+    private final FGCPApi api;
+
+    @Resource
+    protected Logger logger = Logger.NULL;
+
+    @Inject
+    public SystemStatusNormal(FGCPApi api) {
+        this.api = api;
+    }
+
+    public boolean apply(String systemId) {
+        logger.trace("looking for status on system %s", systemId);
+
+        VSystemStatus status = api.getVirtualSystemApi().getStatus(systemId);
+        logger.trace("looking for status on system %s: currently: %s",
+                systemId, status);
+
+        if (status == VSystemStatus.ERROR)
+            throw new IllegalStateException("system in error: " + status);
+        return status == VSystemStatus.NORMAL;
+    }
+
+}
diff --git a/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/compute/strategy/FGCPComputeServiceAdapter.java b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/compute/strategy/FGCPComputeServiceAdapter.java
new file mode 100644
index 0000000..732a8a6
--- /dev/null
+++ b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/compute/strategy/FGCPComputeServiceAdapter.java
@@ -0,0 +1,294 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.fujitsu.fgcp.compute.strategy;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.ExecutionException;
+
+import javax.annotation.Resource;
+import javax.inject.Inject;
+import javax.inject.Named;
+import javax.inject.Singleton;
+
+import org.jclouds.compute.ComputeServiceAdapter;
+import org.jclouds.compute.domain.OsFamily;
+import org.jclouds.compute.domain.Template;
+import org.jclouds.compute.reference.ComputeServiceConstants;
+import org.jclouds.compute.reference.ComputeServiceConstants.Timeouts;
+import org.jclouds.domain.Location;
+import org.jclouds.domain.LoginCredentials;
+import org.jclouds.fujitsu.fgcp.FGCPApi;
+import org.jclouds.fujitsu.fgcp.FGCPAsyncApi;
+import org.jclouds.fujitsu.fgcp.compute.functions.ResourceIdToFirewallId;
+import org.jclouds.fujitsu.fgcp.compute.functions.ResourceIdToSystemId;
+import org.jclouds.fujitsu.fgcp.compute.predicates.ServerStopped;
+import org.jclouds.fujitsu.fgcp.compute.predicates.SystemStatusNormal;
+import org.jclouds.fujitsu.fgcp.compute.strategy.VServerMetadata.Builder;
+import org.jclouds.fujitsu.fgcp.domain.BuiltinServerConfiguration;
+import org.jclouds.fujitsu.fgcp.domain.DiskImage;
+import org.jclouds.fujitsu.fgcp.domain.ServerType;
+import org.jclouds.fujitsu.fgcp.domain.VServer;
+import org.jclouds.fujitsu.fgcp.domain.VServerStatus;
+import org.jclouds.fujitsu.fgcp.domain.VServerWithDetails;
+import org.jclouds.fujitsu.fgcp.domain.VServerWithVNICs;
+import org.jclouds.fujitsu.fgcp.domain.VSystem;
+import org.jclouds.fujitsu.fgcp.domain.VSystemWithDetails;
+import org.jclouds.logging.Logger;
+import org.jclouds.predicates.RetryablePredicate;
+
+import com.google.common.base.Predicate;
+import com.google.common.base.Throwables;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Iterables;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+
+/**
+ * Defines the connection between the {@link org.jclouds.fujitsu.fgcp.FGCPApi}
+ * implementation and the jclouds {@link org.jclouds.compute.ComputeService}.
+ * Bound in FGCPComputeServiceAdapter.
+ * 
+ * @author Dies Koper
+ */
+@Singleton
+public class FGCPComputeServiceAdapter implements
+        ComputeServiceAdapter<VServerMetadata, ServerType, DiskImage, Location> {
+
+    @Resource
+    @Named(ComputeServiceConstants.COMPUTE_LOGGER)
+    protected Logger logger = Logger.NULL;
+
+    private final FGCPApi api;
+    private final FGCPAsyncApi asyncApi;
+    protected Predicate<String> serverStopped = null;
+    protected Predicate<String> serverCreated = null;
+    protected Predicate<String> systemNormal = null;
+    protected ResourceIdToFirewallId toFirewallId = null;
+    protected ResourceIdToSystemId toSystemId = null;
+
+    @Inject
+    public FGCPComputeServiceAdapter(FGCPApi api, FGCPAsyncApi asyncApi,
+            ServerStopped serverStopped, SystemStatusNormal systemNormal,
+            Timeouts timeouts, ResourceIdToFirewallId toFirewallId,
+            ResourceIdToSystemId toSystemId) {
+        this.api = checkNotNull(api, "api");
+        this.asyncApi = checkNotNull(asyncApi, "asyncApi");
+        this.serverStopped = new RetryablePredicate<String>(
+                checkNotNull(serverStopped), timeouts.nodeSuspended);
+        this.serverCreated = new RetryablePredicate<String>(
+                checkNotNull(serverStopped), timeouts.nodeRunning);
+        this.systemNormal = new RetryablePredicate<String>(
+                checkNotNull(systemNormal), timeouts.nodeTerminated);
+        this.toFirewallId = checkNotNull(toFirewallId, "ResourceIdToFirewallId");
+        this.toSystemId = checkNotNull(toSystemId, "ResourceIdToSystemId");
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public NodeAndInitialCredentials<VServerMetadata> createNodeWithGroupEncodedIntoName(
+            String group, String name, Template template) {
+        // Find vsys (how? create new? default to first found?)
+        // Target network DMZ/SECURE1/SECURE2 (how? default to DMZ?)
+        // Determine remaining params: [vserverType,diskImageId,networkId]
+        // what if no vsys exists yet? Location.AU(.contractId) creates 3? tier
+        // skeleton vsys and DMZ is picked?
+        String id = api.getVirtualSystemApi().createServer(name,
+                template.getHardware().getName(), template.getImage().getId(),
+                template.getLocation().getId());
+
+        // wait until fully created (i.e. transitions to stopped status)
+        serverCreated.apply(id);
+        resumeNode(id);
+        VServerMetadata server = getNode(id);
+
+        //do we need this?
+        server.setTemplate(template);
+        String user = template.getImage().getOperatingSystem().getFamily() == OsFamily.WINDOWS ? "Administrator"
+                : "root";
+
+        return new NodeAndInitialCredentials<VServerMetadata>(server,
+                id, LoginCredentials.builder().identity(user)
+                        .password(server.getInitialPassword()).build());
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public Iterable<ServerType> listHardwareProfiles() {
+        return api.getVirtualDCApi().listServerTypes();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public Iterable<DiskImage> listImages() {
+        return api.getVirtualDCApi().listDiskImages();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public DiskImage getImage(String id) {
+        return api.getDiskImageApi().get(id);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public Iterable<Location> listLocations() {
+        // Not using the adapter to determine locations
+        // see SystemAndNetworkSegmentToLocationSupplier
+        return ImmutableSet.<Location> of();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public VServerMetadata getNode(String id) {
+        Builder builder = VServerMetadata.builder();
+        builder.id(id);
+
+        List<ListenableFuture<?>> futures = new ArrayList<ListenableFuture<?>>();
+
+        futures.add(asyncApi.getVirtualServerApi().getDetails(id));
+        futures.add(asyncApi.getVirtualServerApi().getStatus(id));
+        futures.add(asyncApi.getVirtualServerApi().getInitialPassword(id));
+        // mapped public ips?
+        String fwId = toFirewallId.apply(id);
+//        futures.add(asyncApi.getBuiltinServerApi().getConfiguration(fwId,
+//                BuiltinServerConfiguration.SLB_RULE));
+        try {
+            List<Object> results = Futures.successfulAsList(futures).get();
+            VServerWithDetails server = (VServerWithDetails) results.get(0);
+            VServerStatus status = (VServerStatus) results.get(1);
+            System.out.println("getNode(" + id + ")'s getDetails: " + status +" - " + server);
+            if (server == null) {
+                server = api.getVirtualServerApi().getDetails(id);
+                System.out.println("getNode(" + id + ")'s getDetails(2) returns: " + server);
+            }
+            builder.serverWithDetails(server);
+            builder.status(status == null ? VServerStatus.UNRECOGNIZED : status);
+//            System.out.println("status in adapter#getNode: " 
+//            + (VServerStatus) results.get(1) 
+//            +" for " 
+//            + server.getId());
+            builder.initialPassword((String) results.get(2));
+//            SLB slb = ((BuiltinServer) results.get(4)).;
+//            slb.
+        } catch (InterruptedException e) {
+            throw Throwables.propagate(e);
+        } catch (ExecutionException e) {
+            throw Throwables.propagate(e);
+        }
+        return builder.build();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public Iterable<VServerMetadata> listNodes() {
+        ImmutableSet.Builder<VServerMetadata> servers = ImmutableSet
+                .<VServerMetadata> builder();
+
+        Set<VSystem> systems = api.getVirtualDCApi().listVirtualSystems();
+        List<ListenableFuture<VSystemWithDetails>> futures = new ArrayList<ListenableFuture<VSystemWithDetails>>();
+        for (VSystem system : systems) {
+
+            futures.add(asyncApi.getVirtualSystemApi().getDetails(
+                    system.getId()));
+        }
+        try {
+            for (VSystemWithDetails system : Futures.successfulAsList(futures)
+                    .get()) {
+
+                if (system != null) {
+
+                    for (VServerWithVNICs server : system.getServers()) {
+
+                        // skip FW (S-0001) and SLBs (>0 for SLB)
+                        if (!server.getId().endsWith("-S-0001") && server.getVnics().iterator().next().getNicNo() == 0) {
+
+                            servers.add(getNode(server.getId()));
+//                          Builder builder = VServerMetadata.builder();
+//                          builder.server(server);
+//                          builder.status(VServerStatus.UNRECOGNIZED);
+//                          servers.add(builder.build());
+                        }
+                    }
+                }
+            }
+        } catch (InterruptedException e) {
+            throw Throwables.propagate(e);
+        } catch (ExecutionException e) {
+            throw Throwables.propagate(e);
+        }
+
+        return servers.build();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void destroyNode(String id) {
+        api.getVirtualServerApi().destroy(id);
+        // wait until fully destroyed
+        String systemId = toSystemId.apply(id);
+        systemNormal.apply(systemId);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void rebootNode(String id) {
+        suspendNode(id);
+        // wait until fully stopped
+        serverStopped.apply(id);
+        resumeNode(id);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void resumeNode(String id) {
+        api.getVirtualServerApi().start(id);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void suspendNode(String id) {
+        api.getVirtualServerApi().stop(id);
+    }
+}
diff --git a/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/compute/strategy/VServerMetadata.java b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/compute/strategy/VServerMetadata.java
new file mode 100644
index 0000000..e9835ac
--- /dev/null
+++ b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/compute/strategy/VServerMetadata.java
@@ -0,0 +1,178 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.fujitsu.fgcp.compute.strategy;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.util.Set;
+
+import org.jclouds.compute.domain.Template;
+import org.jclouds.fujitsu.fgcp.domain.DiskImage;
+import org.jclouds.fujitsu.fgcp.domain.PublicIP;
+import org.jclouds.fujitsu.fgcp.domain.VServer;
+import org.jclouds.fujitsu.fgcp.domain.VServerStatus;
+import org.jclouds.fujitsu.fgcp.domain.VServerWithVNICs;
+
+import com.google.common.collect.ImmutableSet;
+
+/**
+ * Holds metadata on a virtual server, both static (name, id, type, etc.) and
+ * dynamic (status, mapped public IPs, etc.).
+ * 
+ * @author Dies Koper
+ */
+public class VServerMetadata {
+
+    protected VServer server;
+    protected String id;
+    protected String name;
+    protected Template template;
+    protected String initialPassword;
+    protected VServerStatus status = VServerStatus.UNRECOGNIZED;
+    protected Set<PublicIP> ips;
+    protected DiskImage image;
+
+    public VServerMetadata(VServer server, String initialPassword,
+            VServerStatus status, DiskImage image, Set<PublicIP> publicIps) {
+        this.server = checkNotNull(server, "server");
+        this.initialPassword = initialPassword;
+        this.status = status;
+        this.image = image;
+        this.ips = publicIps;
+        id = server.getId();
+        name = server.getName();
+    }
+
+    public VServerMetadata(String id, String name, Template template,
+            VServerStatus status) {
+        this.id = checkNotNull(id, "id");
+        this.name = checkNotNull(name, "name");
+        this.template = checkNotNull(template, "template");
+        this.status = checkNotNull(status, "status");
+    }
+
+    public VServer getServer() {
+        return server;
+    }
+
+    public String getId() {
+        return id;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public Template getTemplate() {
+        return template;
+    }
+
+    public void setTemplate(Template template) {
+        this.template = template;
+    }
+
+    public String getInitialPassword() {
+        return initialPassword;
+    }
+
+    public VServerStatus getStatus() {
+        return status;
+    }
+
+    public Set<PublicIP> getIps() {
+        return ips;
+    }
+
+    public static Builder builder() {
+        return new Builder();
+    }
+
+    public static class Builder {
+        private VServer server;
+        private VServerWithVNICs serverWithDetails;
+        private String id;
+        private String name;
+        private Template template;
+        private String initialPassword;
+        private VServerStatus status = VServerStatus.UNRECOGNIZED;
+        private Set<PublicIP> publicIps = ImmutableSet.of();
+        private DiskImage image;
+
+        public Builder id(String id) {
+            this.id = id;
+            return this;
+        }
+
+        public Builder name(String name) {
+            this.name = name;
+            return this;
+        }
+
+        public Builder template(Template template) {
+            this.template = template;
+            return this;
+        }
+
+//        public Builder server(VServer server) {
+//            this.server = server;
+//            return this;
+//        }
+
+        public Builder serverWithDetails(VServerWithVNICs serverWithDetails) {
+            this.serverWithDetails = serverWithDetails;
+            return this;
+        }
+
+        public Builder initialPassword(String password) {
+            this.initialPassword = password;
+            return this;
+        }
+
+        public Builder status(VServerStatus status) {
+            this.status = status;
+            return this;
+        }
+
+        public Builder image(DiskImage image) {
+            this.image = image;
+            return this;
+        }
+
+        public Builder publicIps(Set<PublicIP> publicIps) {
+            this.publicIps = publicIps;
+            return this;
+        }
+
+        public VServerMetadata build() {
+            if (initialPassword == null) initialPassword = "";
+            if (server != null) {
+                return new VServerMetadata(server, initialPassword, status,
+                        image, publicIps);
+            } else if (serverWithDetails != null) {
+                return new VServerMetadata(serverWithDetails, initialPassword,
+                        status, image, publicIps);
+            } else {
+                // sometimes these fields are null because the server is returning a verify error
+                if (id == null) id = "dummy-id";
+                if (name == null) name = "dummy-name";
+                return new VServerMetadata(id, name, template, status);
+            }
+        }
+    }
+}
diff --git a/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/domain/AddressRange.java b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/domain/AddressRange.java
new file mode 100644
index 0000000..032a718
--- /dev/null
+++ b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/domain/AddressRange.java
@@ -0,0 +1,57 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.fujitsu.fgcp.domain;
+
+import javax.xml.bind.annotation.XmlRootElement;
+
+/**
+ * Describes the address range pool in a contract used for allocating private IP
+ * address network segments for virtual systems.
+ * 
+ * @author Dies Koper
+ */
+@XmlRootElement(name = "addressrange")
+public class AddressRange {
+    private String range;
+
+    private String from;
+
+    private String to;
+
+    /**
+     * @return the range
+     */
+    public String getRange() {
+        return range;
+    }
+
+    /**
+     * @return the from
+     */
+    public String getFrom() {
+        return from;
+    }
+
+    /**
+     * @return the to
+     */
+    public String getTo() {
+        return to;
+    }
+}
diff --git a/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/domain/BuiltinServer.java b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/domain/BuiltinServer.java
new file mode 100644
index 0000000..911b05c
--- /dev/null
+++ b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/domain/BuiltinServer.java
@@ -0,0 +1,73 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.fujitsu.fgcp.domain;
+
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+
+/**
+ * Represents a built-in server, also called extended function module (EFM),
+ * such as a firewall or load balancer (SLB).
+ * 
+ * @author Dies Koper
+ */
+@XmlRootElement(name = "efm")
+public class BuiltinServer {
+    @XmlElement(name = "efmId")
+    private String id;
+    @XmlElement(name = "efmType")
+    private BuiltinServerType builtinServerType;
+    @XmlElement(name = "efmName")
+    private String name;
+    private String creator;
+    private String slbVip;
+    private Firewall firewall;
+    private SLB loadbalancer;
+
+    public enum BuiltinServerType {FW, SLB}
+
+    public String getId() {
+        return id;
+    }
+
+    public BuiltinServerType getType() {
+        return builtinServerType;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public String getCreator() {
+        return creator;
+    }
+
+    public String getSlbVip() {
+        return slbVip;
+    }
+
+    public Firewall getFirewall() {
+        return firewall;
+    }
+
+    public SLB getLoadbalancer() {
+        return loadbalancer;
+    }
+
+}
diff --git a/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/domain/BuiltinServerBackup.java b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/domain/BuiltinServerBackup.java
new file mode 100644
index 0000000..79374f9
--- /dev/null
+++ b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/domain/BuiltinServerBackup.java
@@ -0,0 +1,75 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.fujitsu.fgcp.domain;
+
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+
+import com.google.common.base.Objects;
+
+/**
+ * Holds information on a backup of a built-in server, such as a firewall or
+ * load balancer (SLB).
+ * 
+ * @author Dies Koper
+ */
+@XmlRootElement(name = "backup")
+public class BuiltinServerBackup {
+    @XmlElement(name = "backupId")
+    private String id;
+    @XmlElement(name = "backupTime")
+    private String time;
+
+    /**
+     * @return the id
+     */
+    public String getId() {
+        return id;
+    }
+
+    /**
+     * @return the time
+     */
+    public String getTime() {
+        return time;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hashCode(id);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj)
+            return true;
+        if (obj == null)
+            return false;
+        if (getClass() != obj.getClass())
+            return false;
+        BuiltinServerBackup that = BuiltinServerBackup.class.cast(obj);
+        return Objects.equal(this.id, that.id);
+    }
+
+    @Override
+    public String toString() {
+        return Objects.toStringHelper(this).omitNullValues().add("id", id)
+                .add("time", time).toString();
+    }
+}
diff --git a/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/domain/BuiltinServerConfiguration.java b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/domain/BuiltinServerConfiguration.java
new file mode 100644
index 0000000..5f7fa6a
--- /dev/null
+++ b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/domain/BuiltinServerConfiguration.java
@@ -0,0 +1,68 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.fujitsu.fgcp.domain;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import com.google.common.base.CaseFormat;
+
+/**
+ * Possible statuses of a built-in server, also called extended function module
+ * (EFM), such as a firewall or load balancer (SLB).
+ * <p>
+ * In addition to statuses that apply to regular virtual servers, it includes
+ * statuses relevant to the upgrade process for functionality of the built-in
+ * server.
+ * 
+ * @author Dies Koper
+ */
+public enum BuiltinServerConfiguration {
+    FW_NAT_RULE,
+    FW_DNS,
+    FW_POLICY,
+    FW_LOG,
+    FW_LIMIT_POLICY,
+    SLB_RULE,
+    SLB_LOAD_STATISTICS,
+    SLB_ERROR_STATISTICS,
+    SLB_CERTIFICATE_LIST,
+    EFM_UPDATE,
+    SLB_CONNECTION,
+    UNRECOGNIZED;
+
+    public String value() {
+        return (CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.UPPER_CAMEL, name()));
+    }
+
+    @Override
+    public String toString() {
+        return value();
+    }
+
+    public static BuiltinServerConfiguration fromValue(String configuration) {
+        try {
+            return valueOf(CaseFormat.UPPER_CAMEL
+                    .to(CaseFormat.UPPER_UNDERSCORE,
+                            checkNotNull(configuration, "configuration")));
+        } catch (IllegalArgumentException e) {
+            return UNRECOGNIZED;
+        }
+    }
+
+}
diff --git a/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/domain/BuiltinServerStatus.java b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/domain/BuiltinServerStatus.java
new file mode 100644
index 0000000..4ee7ba2
--- /dev/null
+++ b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/domain/BuiltinServerStatus.java
@@ -0,0 +1,60 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.fujitsu.fgcp.domain;
+
+import javax.xml.bind.annotation.XmlRootElement;
+
+import com.google.common.base.CaseFormat;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * Possible statuses of a built-in server, also called extended function module
+ * (EFM), such as a firewall or load balancer (SLB).
+ * <p>
+ * In addition to statuses that apply to regular virtual servers, it includes
+ * statuses relevant to the upgrade process for functionality of the built-in
+ * server.
+ * 
+ * @author Dies Koper
+ */
+@XmlRootElement(name = "efmStatus")
+public enum BuiltinServerStatus {
+    DEPLOYING, RUNNING, STOPPING, STOPPED, STARTING, FAILOVER, UNEXPECTED_STOP, RESTORING, BACKUP_ING, ERROR, EXECUTE_NETWORK_SERVER, START_ERROR, STOP_ERROR, UPDATE, BACKOUT, UNRECOGNIZED;
+
+    public String value() {
+        return (CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.UPPER_CAMEL, name()));
+    }
+
+    @Override
+    public String toString() {
+        return value();
+    }
+
+    public static BuiltinServerStatus fromValue(String status) {
+        try {
+            return valueOf(CaseFormat.UPPER_CAMEL
+                    .to(CaseFormat.UPPER_UNDERSCORE,
+                            checkNotNull(status, "status")));
+        } catch (IllegalArgumentException e) {
+            return UNRECOGNIZED;
+        }
+    }
+
+}
diff --git a/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/domain/CPU.java b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/domain/CPU.java
new file mode 100644
index 0000000..b49b9e8
--- /dev/null
+++ b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/domain/CPU.java
@@ -0,0 +1,77 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.fujitsu.fgcp.domain;
+
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+
+import com.google.common.base.Objects;
+
+/**
+ * Describes the virtual CPU of a server.
+ * 
+ * @author Dies Koper
+ */
+@XmlRootElement(name = "cpu")
+public class CPU {
+    @XmlElement(name = "cpuArch")
+    private String arch;
+    @XmlElement(name = "cpuPerf")
+    private double speedPerCore;
+    @XmlElement(name = "numOfCpu")
+    private double cores;
+
+    public String getArch() {
+        return arch;
+    }
+
+    public double getSpeedPerCore() {
+        return speedPerCore;
+    }
+
+    public double getCores() {
+        return cores;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hashCode(cores, speedPerCore, arch);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj)
+            return true;
+        if (obj == null)
+            return false;
+        if (getClass() != obj.getClass())
+            return false;
+        CPU that = CPU.class.cast(obj);
+        return Objects.equal(this.cores, that.cores)
+                && Objects.equal(this.speedPerCore, that.speedPerCore)
+                && Objects.equal(this.arch, that.arch);
+    }
+
+    @Override
+    public String toString() {
+        return Objects.toStringHelper(this).omitNullValues()
+                .add("cores", cores).add("speedPerCore", speedPerCore)
+                .add("arch", arch).toString();
+    }
+}
diff --git a/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/domain/Cause.java b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/domain/Cause.java
new file mode 100644
index 0000000..c2863db
--- /dev/null
+++ b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/domain/Cause.java
@@ -0,0 +1,100 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.fujitsu.fgcp.domain;
+
+
+/**
+ * Represents a load balancer (SLB) log entry.
+ * 
+ * @author Dies Koper
+ */
+public class Cause {
+    private String cat;
+
+    private String status;
+
+    private String filePath;
+
+    private String current;
+
+    private String before;
+
+    private String today;
+
+    private String yesterday;
+
+    private String total;
+
+    /**
+     * @return category
+     */
+    public String getCat() {
+        return cat;
+    }
+
+    /**
+     * @return the status
+     */
+    public String getStatus() {
+        return status;
+    }
+
+    /**
+     * @return the filePath
+     */
+    public String getFilePath() {
+        return filePath;
+    }
+
+    /**
+     * @return the current
+     */
+    public String getCurrent() {
+        return current;
+    }
+
+    /**
+     * @return the before
+     */
+    public String getBefore() {
+        return before;
+    }
+
+    /**
+     * @return the today
+     */
+    public String getToday() {
+        return today;
+    }
+
+    /**
+     * @return the yesterday
+     */
+    public String getYesterday() {
+        return yesterday;
+    }
+
+    /**
+     * @return the total
+     */
+    public String getTotal() {
+        return total;
+    }
+
+}
diff --git a/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/domain/Direction.java b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/domain/Direction.java
new file mode 100644
index 0000000..b332fdc
--- /dev/null
+++ b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/domain/Direction.java
@@ -0,0 +1,113 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.fujitsu.fgcp.domain;
+
+import java.util.LinkedHashSet;
+import java.util.Set;
+
+import com.google.common.base.Objects;
+import com.google.common.collect.ImmutableSet;
+
+/**
+ * Grouping of firewall rules pertaining to a particular direction in network
+ * traffic, e.g. from the Internet to a server in the DMZ zone, or from a server
+ * in the SECURE2 zone to the SECURE1 zone, etc.
+ * 
+ * @author Dies Koper
+ */
+public class Direction {
+    private String from;
+    private String to;
+    private Set<Policy> policies = new LinkedHashSet<Policy>();
+    private Acceptable acceptable;
+    private Prefix prefix;
+    private int maxPolicyNum;
+
+    enum Acceptable {OK, NG}
+    enum Prefix {free, src, dst, proto, srcport, dstport, action, rule, tab}
+
+    /**
+     * @return the from
+     */
+    public String getFrom() {
+        return from;
+    }
+
+    /**
+     * @return the to
+     */
+    public String getTo() {
+        return to;
+    }
+
+    /**
+     * @return the policies
+     */
+    public Set<Policy> getPolicies() {
+        return policies == null ? ImmutableSet.<Policy> of() : ImmutableSet
+                .copyOf(policies);
+    }
+
+    /**
+     * @return the acceptable
+     */
+    public Acceptable getAcceptable() {
+        return acceptable;
+    }
+
+    /**
+     * @return the prefix
+     */
+    public Prefix getPrefix() {
+        return prefix;
+    }
+
+    /**
+     * @return the maxPolicyNum
+     */
+    public int getMaxPolicyNum() {
+        return maxPolicyNum;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hashCode(from, to);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj)
+            return true;
+        if (obj == null)
+            return false;
+        if (getClass() != obj.getClass())
+            return false;
+        Direction that = Direction.class.cast(obj);
+        return Objects.equal(this.from, that.from)
+                && Objects.equal(this.to, that.to);
+    }
+
+    @Override
+    public String toString() {
+        return Objects.toStringHelper(this).omitNullValues().add("from", from)
+                .add("to", to).add("prefix", prefix).add("policies", policies)
+                .add("maxPolicyNum", maxPolicyNum)
+                .add("acceptable", acceptable).toString();
+    }
+}
diff --git a/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/domain/Disk.java b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/domain/Disk.java
new file mode 100644
index 0000000..dae088f
--- /dev/null
+++ b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/domain/Disk.java
@@ -0,0 +1,85 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.fujitsu.fgcp.domain;
+
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+
+/**
+ * Describes a disk as part of the description of hardware represented by a
+ * virtual server.
+ * 
+ * @author Dies Koper
+ */
+@XmlRootElement
+public class Disk {
+    @XmlElement(name = "diskSize")
+    private String size;
+
+    @XmlElement(name = "diskUsage")
+    private String usage;
+
+    @XmlElement(name = "diskType")
+    private String type;
+
+    public String getSize() {
+        return size;
+    }
+
+    public String getUsage() {
+        return usage;
+    }
+
+    public String getType() {
+        return type;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o)
+            return true;
+        if (!(o instanceof Disk))
+            return false;
+
+        Disk disk = (Disk) o;
+
+        if (size != null ? !size.equals(disk.size) : disk.size != null)
+            return false;
+        if (type != null ? !type.equals(disk.type) : disk.type != null)
+            return false;
+        if (usage != null ? !usage.equals(disk.usage) : disk.usage != null)
+            return false;
+
+        return true;
+    }
+
+    @Override
+    public int hashCode() {
+        int result = size != null ? size.hashCode() : 0;
+        result = 31 * result + (usage != null ? usage.hashCode() : 0);
+        result = 31 * result + (type != null ? type.hashCode() : 0);
+        return result;
+    }
+
+    @Override
+    public String toString() {
+        return "Disk{" + "size='" + size + '\'' + ", usage='" + usage + '\''
+                + ", type='" + type + '\'' + '}';
+    }
+}
diff --git a/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/domain/DiskImage.java b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/domain/DiskImage.java
new file mode 100644
index 0000000..5e2d3e1
--- /dev/null
+++ b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/domain/DiskImage.java
@@ -0,0 +1,200 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.fujitsu.fgcp.domain;
+
+import java.util.LinkedHashSet;
+import java.util.Set;
+
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlElementWrapper;
+import javax.xml.bind.annotation.XmlRootElement;
+
+import com.google.common.base.Objects;
+import com.google.common.collect.ImmutableSet;
+
+/**
+ * Represents a disk image with pre-installed OS and/or software.
+ * <p>
+ * It is used as base for the system disk of a virtual server.
+ * 
+ * @author Dies Koper
+ */
+@XmlRootElement(name = "diskimage")
+public class DiskImage {
+    @XmlElement(name = "diskimageId")
+    private String id;
+
+    @XmlElement(name = "diskimageName")
+    private String name;
+
+    private int size;
+
+    private String osName;
+
+    private String osType;
+
+    private String creatorName;
+
+    private String registrant;
+
+    private String licenseInfo;
+
+    private String description;
+
+    @XmlElementWrapper(name = "softwares")
+    @XmlElement(name = "software")
+    private Set<Software> software = new LinkedHashSet<Software>();
+
+    public String getId() {
+        return id;
+    }
+
+    public int getSize() {
+        return size;
+    }
+
+    public String getOsName() {
+        return osName;
+    }
+
+    public String getOsType() {
+        return osType;
+    }
+
+    public String getCreatorName() {
+        return creatorName;
+    }
+
+    public String getRegistrant() {
+        return registrant;
+    }
+
+    public String getLicenseInfo() {
+        return licenseInfo;
+    }
+
+    public String getDescription() {
+        return description;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public Set<Software> getSoftware() {
+        return software == null ? ImmutableSet.<Software> of() : ImmutableSet
+                .copyOf(software);
+    }
+
+    public static Builder builder() {
+        return new Builder();
+    }
+
+    public static class Builder {
+        private String id;
+        private String name;
+        private int size;
+        private String osName;
+        private String osType;
+        private String creatorName;
+        private String registrant;
+        private String licenseInfo;
+        private String description;
+        private Set<Software> software;
+
+        public Builder id(String id) {
+            this.id = id;
+            return this;
+        }
+
+        public Builder name(String name) {
+            this.name = name;
+            return this;
+        }
+
+        public Builder osName(String osName) {
+            this.osName = osName;
+            return this;
+        }
+
+        public Builder osType(String osType) {
+            this.osType = osType;
+            return this;
+        }
+
+        public Builder creatorName(String creatorName) {
+            this.creatorName = creatorName;
+            return this;
+        }
+
+        public Builder registrant(String registrant) {
+            this.registrant = registrant;
+            return this;
+        }
+
+        public Builder description(String description) {
+            this.description = description;
+            return this;
+        }
+
+        public DiskImage build() {
+            DiskImage image = new DiskImage();
+
+            image.id = id;
+            image.name = name;
+            image.size = size;
+            image.osName = osName;
+            image.osType = osType;
+            image.creatorName = creatorName;
+            image.registrant = registrant;
+            image.licenseInfo = licenseInfo;
+            image.description = description;
+            image.software = software;
+
+            return image;
+        }
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hashCode(id);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj)
+            return true;
+        if (obj == null)
+            return false;
+        if (getClass() != obj.getClass())
+            return false;
+        DiskImage that = DiskImage.class.cast(obj);
+        return Objects.equal(this.id, that.id);
+    }
+
+    @Override
+    public String toString() {
+        return Objects.toStringHelper(this).omitNullValues().add("id", id)
+                .add("name", name).add("osName", osName).add("osType", osType)
+                .add("size", size).add("creatorName", creatorName)
+                .add("description", description)
+                .add("licenseInfo", licenseInfo).add("registrant", registrant)
+                .add("software", software).toString();
+    }
+}
diff --git a/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/domain/ErrorStatistics.java b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/domain/ErrorStatistics.java
new file mode 100644
index 0000000..28cb1e7
--- /dev/null
+++ b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/domain/ErrorStatistics.java
@@ -0,0 +1,53 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.fujitsu.fgcp.domain;
+
+import java.util.LinkedHashSet;
+import java.util.Set;
+
+import javax.xml.bind.annotation.XmlRootElement;
+
+import com.google.common.collect.ImmutableSet;
+
+/**
+ * Holds statistics of errors reported by a load balancer (SLB).
+ * 
+ * @author Dies Koper
+ */
+@XmlRootElement(name = "errorstatistics")
+public class ErrorStatistics {
+    private Period period;
+    private Set<Group> groups = new LinkedHashSet<Group>();
+
+    /**
+     * @return the period
+     */
+    public Period getPeriod() {
+        return period;
+    }
+
+    /**
+     * @return the groups
+     */
+    public Set<Group> getGroups() {
+        return groups == null ? ImmutableSet.<Group> of() : ImmutableSet
+                .copyOf(groups);
+    }
+
+}
diff --git a/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/domain/EventLog.java b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/domain/EventLog.java
new file mode 100644
index 0000000..bda7e23
--- /dev/null
+++ b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/domain/EventLog.java
@@ -0,0 +1,99 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.fujitsu.fgcp.domain;
+
+import javax.xml.bind.annotation.XmlRootElement;
+
+import com.google.common.base.Objects;
+
+/**
+ * Represents an entry in the event log.
+ * 
+ * @author Dies Koper
+ */
+@XmlRootElement(name = "errorlog")
+public class EventLog {
+    private String title;
+    private String message;
+    private String startDate;
+    private String expiry;
+    private String entryDate;
+
+    /**
+     * @return the title
+     */
+    public String getTitle() {
+        return title;
+    }
+
+    /**
+     * @return the message
+     */
+    public String getMessage() {
+        return message;
+    }
+
+    /**
+     * @return the startDate
+     */
+    public String getStartDate() {
+        return startDate;
+    }
+
+    /**
+     * @return the expiry
+     */
+    public String getExpiry() {
+        return expiry;
+    }
+
+    /**
+     * @return the entryDate
+     */
+    public String getEntryDate() {
+        return entryDate;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hashCode(entryDate, message, title);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj)
+            return true;
+        if (obj == null)
+            return false;
+        if (getClass() != obj.getClass())
+            return false;
+        EventLog that = EventLog.class.cast(obj);
+        return Objects.equal(this.entryDate, that.entryDate)
+                && Objects.equal(this.message, that.message)
+                && Objects.equal(this.title, that.title);
+    }
+
+    @Override
+    public String toString() {
+        return Objects.toStringHelper(this).omitNullValues()
+                .add("entryDate", entryDate).add("title", title)
+                .add("message", message).add("startDate", startDate)
+                .add("expiry", expiry).toString();
+    }
+}
diff --git a/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/domain/Firewall.java b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/domain/Firewall.java
new file mode 100644
index 0000000..f466c05
--- /dev/null
+++ b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/domain/Firewall.java
@@ -0,0 +1,133 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.fujitsu.fgcp.domain;
+
+import java.util.LinkedHashSet;
+import java.util.Set;
+
+import javax.xml.bind.annotation.XmlRootElement;
+
+import com.google.common.collect.ImmutableSet;
+
+/**
+ * Represents a firewall (FW).
+ * 
+ * @author Dies Koper
+ */
+@XmlRootElement(name = "fw")
+public class Firewall {
+    private NAT nat;
+    private Set<Direction> directions = new LinkedHashSet<Direction>();
+    private String log;
+    private String status;
+    private String category;
+    private String latestVersion;
+    private String comment;
+    private boolean firmUpdateExist;
+    private boolean configUpdateExist;
+    private String backout;
+    private String updateDate;
+    private String currentVersion;
+
+    /**
+     * @return the nat
+     */
+    public NAT getNat() {
+        return nat;
+    }
+
+    /**
+     * @return the directions
+     */
+    public Set<Direction> getDirections() {
+        return directions == null ? ImmutableSet.<Direction> of()
+                : ImmutableSet.copyOf(directions);
+    }
+
+    /**
+     * @return the log
+     */
+    public String getLog() {
+        return log;
+    }
+
+    /**
+     * @return the status
+     */
+    public String getStatus() {
+        return status;
+    }
+
+    /**
+     * @return the category
+     */
+    public String getCategory() {
+        return category;
+    }
+
+    /**
+     * @return the latestVersion
+     */
+    public String getLatestVersion() {
+        return latestVersion;
+    }
+
+    /**
+     * @return the comment
+     */
+    public String getComment() {
+        return comment;
+    }
+
+    /**
+     * @return the firmUpdateExist
+     */
+    public boolean getFirmUpdateExist() {
+        return firmUpdateExist;
+    }
+
+    /**
+     * @return the configUpdateExist
+     */
+    public boolean getConfigUpdateExist() {
+        return configUpdateExist;
+    }
+
+    /**
+     * @return the backout
+     */
+    public String getBackout() {
+        return backout;
+    }
+
+    /**
+     * @return the updateDate
+     */
+    public String getUpdateDate() {
+        return updateDate;
+    }
+
+    /**
+     * @return the currentVersion
+     */
+    public String getCurrentVersion() {
+        return currentVersion;
+    }
+
+}
diff --git a/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/domain/Group.java b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/domain/Group.java
new file mode 100644
index 0000000..40c36a4
--- /dev/null
+++ b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/domain/Group.java
@@ -0,0 +1,226 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.fujitsu.fgcp.domain;
+
+import java.util.LinkedHashSet;
+import java.util.Set;
+
+import javax.xml.bind.annotation.XmlEnumValue;
+
+import com.google.common.base.Objects;
+import com.google.common.collect.ImmutableSet;
+
+/**
+ * Describes attributes of a software load balancer's (SLB) configuration.
+ * 
+ * @author Dies Koper
+ */
+public class Group {
+    private int id;
+
+    private String protocol;
+
+    private int port1;
+
+    private int port2;
+
+    private String balanceType;
+
+    private String uniqueType;
+
+    private String monitorType;
+
+    private int maxConnection;
+
+    private int uniqueRetention;
+
+    private int interval;
+
+    private int timeout;
+
+    private int retryCount;
+
+    private int certNum;
+
+    private Set<Cause> causes;
+
+    private RecoveryAction recoveryAction;
+
+    private Set<Target> targets = new LinkedHashSet<Target>();
+
+    private String validity;
+
+    enum RecoveryAction {
+        @XmlEnumValue("switch-back")
+        SWITCH_BACK, @XmlEnumValue("maintenance")
+        MAINTENANCE
+    }
+
+    /**
+     * @return the id
+     */
+    public int getId() {
+        return id;
+    }
+
+    /**
+     * @return the protocol
+     */
+    public String getProtocol() {
+        return protocol;
+    }
+
+    /**
+     * @return the port1
+     */
+    public int getPort1() {
+        return port1;
+    }
+
+    /**
+     * @return the port2
+     */
+    public int getPort2() {
+        return port2;
+    }
+
+    /**
+     * @return the balanceType
+     */
+    public String getBalanceType() {
+        return balanceType;
+    }
+
+    /**
+     * @return the uniqueType
+     */
+    public String getUniqueType() {
+        return uniqueType;
+    }
+
+    /**
+     * @return the monitorType
+     */
+    public String getMonitorType() {
+        return monitorType;
+    }
+
+    /**
+     * @return the maxConnection
+     */
+    public int getMaxConnection() {
+        return maxConnection;
+    }
+
+    /**
+     * @return the uniqueRetention
+     */
+    public int getUniqueRetention() {
+        return uniqueRetention;
+    }
+
+    /**
+     * @return the interval
+     */
+    public int getInterval() {
+        return interval;
+    }
+
+    /**
+     * @return the timeout
+     */
+    public int getTimeout() {
+        return timeout;
+    }
+
+    /**
+     * @return the retryCount
+     */
+    public int getRetryCount() {
+        return retryCount;
+    }
+
+    /**
+     * @return the certNum
+     */
+    public int getCertNum() {
+        return certNum;
+    }
+
+    /**
+     * @return the causes
+     */
+    public Set<Cause> getCauses() {
+        return causes == null ? ImmutableSet.<Cause> of() : ImmutableSet
+                .copyOf(causes);
+    }
+
+    /**
+     * @return the recoveryAction
+     */
+    public RecoveryAction getRecoveryAction() {
+        return recoveryAction;
+    }
+
+    /**
+     * @return the targets
+     */
+    public Set<Target> getTargets() {
+        return targets == null ? ImmutableSet.<Target> of() : ImmutableSet
+                .copyOf(targets);
+    }
+
+    /**
+     * @return the validity
+     */
+    public String getValidity() {
+        return validity;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hashCode(id);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj)
+            return true;
+        if (obj == null)
+            return false;
+        if (getClass() != obj.getClass())
+            return false;
+        Group that = Group.class.cast(obj);
+        return Objects.equal(this.id, that.id);
+    }
+
+    @Override
+    public String toString() {
+        return Objects.toStringHelper(this).omitNullValues().add("id", id)
+                .add("protocol", protocol).add("port1", port1)
+                .add("port2", port2).add("balanceType", balanceType)
+                .add("uniqueType", uniqueType).add("monitorType", monitorType)
+                .add("maxConnection", maxConnection)
+                .add("uniqueRetention", uniqueRetention)
+                .add("interval", interval).add("timeout", timeout)
+                .add("retryCount", retryCount).add("certNum", certNum)
+                .add("causes", causes).add("recoveryAction", recoveryAction)
+                .add("targets", targets).add("validity", validity).toString();
+    }
+}
diff --git a/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/domain/Image.java b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/domain/Image.java
new file mode 100644
index 0000000..ed8fbac
--- /dev/null
+++ b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/domain/Image.java
@@ -0,0 +1,114 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.fujitsu.fgcp.domain;
+
+import java.util.LinkedHashSet;
+import java.util.Set;
+
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlElementWrapper;
+
+import com.google.common.base.Objects;
+import com.google.common.collect.ImmutableSet;
+
+/**
+ * Holds information on the system disk image of a virtual server, including the
+ * OS and software pre-installed on it.
+ * 
+ * @author Dies Koper
+ */
+public class Image {
+    private String id;
+
+    private String serverCategory;
+
+    private String serverApplication;
+
+    private String cpuBit;
+
+    private float sysvolSize;
+
+    private int numOfMaxDisk;
+
+    private int numOfMaxNic;
+
+    @XmlElementWrapper(name = "softwares")
+    @XmlElement(name = "software")
+    private Set<Software> software = new LinkedHashSet<Software>();
+
+    public String getId() {
+        return id;
+    }
+
+    public String getServerCategory() {
+        return serverCategory;
+    }
+
+    public String getServerApplication() {
+        return serverApplication;
+    }
+
+    public String getCpuBit() {
+        return cpuBit;
+    }
+
+    public float getSysvolSize() {
+        return sysvolSize;
+    }
+
+    public int getNumOfMaxDisk() {
+        return numOfMaxDisk;
+    }
+
+    public int getNumOfMaxNic() {
+        return numOfMaxNic;
+    }
+
+    public Set<Software> getSoftware() {
+        return software == null ? ImmutableSet.<Software> of() : ImmutableSet
+                .copyOf(software);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hashCode(id);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj)
+            return true;
+        if (obj == null)
+            return false;
+        if (getClass() != obj.getClass())
+            return false;
+        Image that = Image.class.cast(obj);
+        return Objects.equal(this.id, that.id);
+    }
+
+    @Override
+    public String toString() {
+        return Objects.toStringHelper(this).omitNullValues().add("id", id)
+                .add("serverCategory", serverCategory)
+                .add("serverApplication", serverApplication)
+                .add("cpuBit", cpuBit).add("sysvolSize", sysvolSize)
+                .add("numOfMaxDisk", numOfMaxDisk)
+                .add("numOfMaxNic", numOfMaxNic).toString();
+    }
+}
diff --git a/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/domain/Information.java b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/domain/Information.java
new file mode 100644
index 0000000..a8a822f
--- /dev/null
+++ b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/domain/Information.java
@@ -0,0 +1,105 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.fujitsu.fgcp.domain;
+
+import com.google.common.base.Objects;
+
+/**
+ * Holds information relating to the FGCP service.
+ * 
+ * @author Dies Koper
+ */
+public class Information {
+    private int seqno;
+    private String title;
+    private String message;
+    private String startDate;
+    private String expiry;
+    private String entryDate;
+
+    /**
+     * @return the seqno
+     */
+    public int getSeqno() {
+        return seqno;
+    }
+
+    /**
+     * @return the title
+     */
+    public String getTitle() {
+        return title;
+    }
+
+    /**
+     * @return the message
+     */
+    public String getMessage() {
+        return message;
+    }
+
+    /**
+     * @return the startDate
+     */
+    public String getStartDate() {
+        return startDate;
+    }
+
+    /**
+     * @return the expiry
+     */
+    public String getExpiry() {
+        return expiry;
+    }
+
+    /**
+     * @return the entryDate
+     */
+    public String getEntryDate() {
+        return entryDate;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hashCode(seqno, entryDate, message, title);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj)
+            return true;
+        if (obj == null)
+            return false;
+        if (getClass() != obj.getClass())
+            return false;
+        Information that = Information.class.cast(obj);
+        return Objects.equal(this.seqno, that.seqno)
+                && Objects.equal(this.entryDate, that.entryDate)
+                && Objects.equal(this.message, that.message)
+                && Objects.equal(this.title, that.title);
+    }
+
+    @Override
+    public String toString() {
+        return Objects.toStringHelper(this).omitNullValues()
+                .add("seqno", seqno).add("entryDate", entryDate)
+                .add("title", title).add("message", message)
+                .add("startDate", startDate).add("expiry", expiry).toString();
+    }
+}
diff --git a/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/domain/IntermediateCACert.java b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/domain/IntermediateCACert.java
new file mode 100644
index 0000000..7acc387
--- /dev/null
+++ b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/domain/IntermediateCACert.java
@@ -0,0 +1,120 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.fujitsu.fgcp.domain;
+
+import javax.xml.bind.annotation.XmlRootElement;
+
+import com.google.common.base.Objects;
+
+/**
+ * Describes an intermediate CA certificate for use with a load balancer (SLB).
+ * 
+ * @author Dies Koper
+ */
+@XmlRootElement(name = "ccacert")
+public class IntermediateCACert implements Comparable<IntermediateCACert> {
+    private int ccacertNum;
+
+    private String description;
+
+    private String subject;
+
+    private String issuer;
+
+    private String validity;
+
+    private String detail;
+
+    /**
+     * @return the ccacertNum
+     */
+    public int getCcacertNum() {
+        return ccacertNum;
+    }
+
+    /**
+     * @return the description
+     */
+    public String getDescription() {
+        return description;
+    }
+
+    /**
+     * @return the subject
+     */
+    public String getSubject() {
+        return subject;
+    }
+
+    /**
+     * @return the issuer
+     */
+    public String getIssuer() {
+        return issuer;
+    }
+
+    /**
+     * @return the validity
+     */
+    public String getValidity() {
+        return validity;
+    }
+
+    /**
+     * @return the detail
+     */
+    public String getDetail() {
+        return detail;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hashCode(ccacertNum, issuer, subject, validity);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj)
+            return true;
+        if (obj == null)
+            return false;
+        if (getClass() != obj.getClass())
+            return false;
+        IntermediateCACert that = IntermediateCACert.class.cast(obj);
+        return Objects.equal(this.ccacertNum, that.ccacertNum)
+                && Objects.equal(this.issuer, that.issuer)
+                && Objects.equal(this.subject, that.subject)
+                && Objects.equal(this.validity, that.validity);
+    }
+
+    @Override
+    public String toString() {
+        return Objects.toStringHelper(this).omitNullValues()
+                .add("ccacertNum", ccacertNum).add("issuer", issuer)
+                .add("subject", subject).add("validity", validity)
+                .add("description", description).add("detail", detail)
+                .toString();
+    }
+
+    @Override
+    public int compareTo(IntermediateCACert o) {
+        return ccacertNum - o.ccacertNum;
+    }
+
+}
diff --git a/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/domain/LoadStatistics.java b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/domain/LoadStatistics.java
new file mode 100644
index 0000000..654e4fc
--- /dev/null
+++ b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/domain/LoadStatistics.java
@@ -0,0 +1,68 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.fujitsu.fgcp.domain;
+
+import java.util.LinkedHashSet;
+import java.util.Set;
+
+import javax.xml.bind.annotation.XmlRootElement;
+
+import com.google.common.base.Objects;
+import com.google.common.collect.ImmutableSet;
+
+/**
+ * Holds statistics of the load on a load balancer (SLB).
+ * 
+ * @author Dies Koper
+ */
+@XmlRootElement(name = "loadstatistics")
+public class LoadStatistics {
+    private Set<Group> groups = new LinkedHashSet<Group>();
+
+    /**
+     * @return the groups
+     */
+    public Set<Group> getGroups() {
+        return groups == null ? ImmutableSet.<Group> of() : ImmutableSet
+                .copyOf(groups);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hashCode(groups);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj)
+            return true;
+        if (obj == null)
+            return false;
+        if (getClass() != obj.getClass())
+            return false;
+        LoadStatistics that = LoadStatistics.class.cast(obj);
+        return Objects.equal(this.groups, that.groups);
+    }
+
+    @Override
+    public String toString() {
+        return Objects.toStringHelper(this).omitNullValues()
+                .add("groups", groups).toString();
+    }
+}
diff --git a/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/domain/Memory.java b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/domain/Memory.java
new file mode 100644
index 0000000..af3b076
--- /dev/null
+++ b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/domain/Memory.java
@@ -0,0 +1,66 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.fujitsu.fgcp.domain;
+
+import javax.xml.bind.annotation.XmlElement;
+
+import com.google.common.base.Objects;
+
+/**
+ * Represents the memory of a virtual server.
+ * 
+ * @author Dies Koper
+ */
+public class Memory implements Comparable<Memory> {
+    @XmlElement(name = "memorySize")
+    private double size;
+
+    public double getSize() {
+        return size;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hashCode(size);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj)
+            return true;
+        if (obj == null)
+            return false;
+        if (getClass() != obj.getClass())
+            return false;
+        Memory that = Memory.class.cast(obj);
+        return Objects.equal(this.size, that.size);
+    }
+
+    @Override
+    public String toString() {
+        return Objects.toStringHelper(this).omitNullValues().add("size", size)
+                .toString();
+    }
+
+    @Override
+    public int compareTo(Memory o) {
+        return Double.compare(size, o.size);
+    }
+
+}
diff --git a/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/domain/NAT.java b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/domain/NAT.java
new file mode 100644
index 0000000..a753ed8
--- /dev/null
+++ b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/domain/NAT.java
@@ -0,0 +1,65 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.fujitsu.fgcp.domain;
+
+import java.util.LinkedHashSet;
+import java.util.Set;
+
+import com.google.common.base.Objects;
+import com.google.common.collect.ImmutableSet;
+
+/**
+ * Holds the network address translation rules of a firewall.
+ * 
+ * @author Dies Koper
+ */
+public class NAT {
+    private Set<Rule> rules = new LinkedHashSet<Rule>();
+
+    /**
+     * @return the rules
+     */
+    public Set<Rule> getRules() {
+        return rules == null ? ImmutableSet.<Rule> of() : ImmutableSet
+                .copyOf(rules);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hashCode(rules);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj)
+            return true;
+        if (obj == null)
+            return false;
+        if (getClass() != obj.getClass())
+            return false;
+        NAT that = NAT.class.cast(obj);
+        return Objects.equal(this.rules, that.rules);
+    }
+
+    @Override
+    public String toString() {
+        return Objects.toStringHelper(this).omitNullValues()
+                .add("rules", rules).toString();
+    }
+}
diff --git a/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/domain/PerformanceInfo.java b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/domain/PerformanceInfo.java
new file mode 100644
index 0000000..e9d9856
--- /dev/null
+++ b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/domain/PerformanceInfo.java
@@ -0,0 +1,149 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.fujitsu.fgcp.domain;
+
+import javax.xml.bind.annotation.XmlRootElement;
+
+import com.google.common.base.Objects;
+
+/**
+ * Holds the statistics of a virtual server.
+ * 
+ * @author Dies Koper
+ */
+@XmlRootElement(name = "performanceinfo")
+public class PerformanceInfo implements Comparable<PerformanceInfo> {
+    private long recordTime;
+    private double cpuUtilization;
+    private long diskReadRequestCount;
+    private long diskWriteRequestCount;
+    private long diskReadSector;
+    private long diskWriteSector;
+    private long nicInputByte;
+    private long nicOutputByte;
+    private long nicInputPacket;
+    private long nicOutputPacket;
+
+    /**
+     * @return the recordTime
+     */
+    public long getRecordTime() {
+        return recordTime;
+    }
+
+    /**
+     * @return the cpuUtilization
+     */
+    public double getCpuUtilization() {
+        return cpuUtilization;
+    }
+
+    /**
+     * @return the diskReadRequestCount
+     */
+    public long getDiskReadRequestCount() {
+        return diskReadRequestCount;
+    }
+
+    /**
+     * @return the diskWriteRequestCount
+     */
+    public long getDiskWriteRequestCount() {
+        return diskWriteRequestCount;
+    }
+
+    /**
+     * @return the diskReadSector
+     */
+    public long getDiskReadSector() {
+        return diskReadSector;
+    }
+
+    /**
+     * @return the diskWriteSector
+     */
+    public long getDiskWriteSector() {
+        return diskWriteSector;
+    }
+
+    /**
+     * @return the nicInputByte
+     */
+    public long getNicInputByte() {
+        return nicInputByte;
+    }
+
+    /**
+     * @return the nicOutputByte
+     */
+    public long getNicOutputByte() {
+        return nicOutputByte;
+    }
+
+    /**
+     * @return the nicInputPacket
+     */
+    public long getNicInputPacket() {
+        return nicInputPacket;
+    }
+
+    /**
+     * @return the nicOutputPacket
+     */
+    public long getNicOutputPacket() {
+        return nicOutputPacket;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hashCode(recordTime);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj)
+            return true;
+        if (obj == null)
+            return false;
+        if (getClass() != obj.getClass())
+            return false;
+        PerformanceInfo that = PerformanceInfo.class.cast(obj);
+        return Objects.equal(this.recordTime, that.recordTime);
+    }
+
+    @Override
+    public String toString() {
+        return Objects.toStringHelper(this).omitNullValues()
+                .add("recordTime", recordTime)
+                .add("cpuUtilization", cpuUtilization)
+                .add("diskReadRequestCount", diskReadRequestCount)
+                .add("diskWriteRequestCount", diskWriteRequestCount)
+                .add("diskReadSector", diskReadSector)
+                .add("diskWriteSector", diskWriteSector)
+                .add("nicInputByte", nicInputByte)
+                .add("nicOutputByte", nicOutputByte)
+                .add("nicInputPacket", nicInputPacket)
+                .add("nicOutputPacket", nicOutputPacket).toString();
+    }
+
+    @Override
+    public int compareTo(PerformanceInfo o) {
+        return (int) (recordTime - o.recordTime);
+    }
+}
diff --git a/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/domain/Period.java b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/domain/Period.java
new file mode 100644
index 0000000..b75173f
--- /dev/null
+++ b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/domain/Period.java
@@ -0,0 +1,61 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.fujitsu.fgcp.domain;
+
+/**
+ * Describes the period over which error statistics of a load balancer (SLB) are
+ * kept.
+ * 
+ * @author Dies Koper
+ */
+public class Period {
+    private String current;
+    private String before;
+    private String today;
+    private String yesterday;
+
+    /**
+     * @return the current
+     */
+    public String getCurrent() {
+        return current;
+    }
+
+    /**
+     * @return the before
+     */
+    public String getBefore() {
+        return before;
+    }
+
+    /**
+     * @return the today
+     */
+    public String getToday() {
+        return today;
+    }
+
+    /**
+     * @return the yesterday
+     */
+    public String getYesterday() {
+        return yesterday;
+    }
+
+}
diff --git a/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/domain/Policy.java b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/domain/Policy.java
new file mode 100644
index 0000000..e030c12
--- /dev/null
+++ b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/domain/Policy.java
@@ -0,0 +1,195 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.fujitsu.fgcp.domain;
+
+import javax.xml.bind.annotation.XmlEnumValue;
+
+import com.google.common.base.Objects;
+
+/**
+ * Describes a firewall rule in detail.
+ * 
+ * @author Dies Koper
+ */
+public class Policy implements Comparable<Policy> {
+    private int id;
+
+    private String src;
+
+    private PolicyType srcType;
+
+    private String srcPort;
+
+    private Service dstService;
+
+    private String dst;
+
+    private PolicyType dstType;
+
+    private String dstPort;
+
+    private Protocol protocol;
+
+    private Action action;
+
+    private Log log;
+
+    enum Service {
+        NONE, WSUS, DNS, NTP, @XmlEnumValue("yum")
+        YUM, KMS, @XmlEnumValue("Symantec")
+        SYMANTEC, RHUI
+    }
+
+    enum PolicyType {IP, FQDN, FQDNF}
+
+    enum Protocol {
+        @XmlEnumValue("tcp")
+        TCP, @XmlEnumValue("udp")
+        UDP, @XmlEnumValue("tcp-udp")
+        TCP_UDP, @XmlEnumValue("icmp")
+        ICMP
+    }
+
+    enum Action {
+        @XmlEnumValue("Accept")
+        ACCEPT, @XmlEnumValue("Deny")
+        DENY
+    }
+
+    enum Log {
+        @XmlEnumValue("On")
+        ON, @XmlEnumValue("Off")
+        OFF
+    }
+
+    /**
+     * @return the id
+     */
+    public int getId() {
+        return id;
+    }
+
+    /**
+     * @return the src
+     */
+    public String getSrc() {
+        return src;
+    }
+
+    /**
+     * @return the srcType
+     */
+    public PolicyType getSrcType() {
+        return srcType;
+    }
+
+    /**
+     * @return the srcPort
+     */
+    public String getSrcPort() {
+        return srcPort;
+    }
+
+    /**
+     * @return the dstService
+     */
+    public Service getDstService() {
+        return dstService;
+    }
+
+    /**
+     * @return the dst
+     */
+    public String getDst() {
+        return dst;
+    }
+
+    /**
+     * @return the dstType
+     */
+    public PolicyType getDstType() {
+        return dstType;
+    }
+
+    /**
+     * @return the dstPort
+     */
+    public String getDstPort() {
+        return dstPort;
+    }
+
+    /**
+     * @return the protocol
+     */
+    public Protocol getProtocol() {
+        return protocol;
+    }
+
+    /**
+     * @return the action
+     */
+    public Action getAction() {
+        return action;
+    }
+
+    /**
+     * @return the log
+     */
+    public Log getLog() {
+        return log;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hashCode(id);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj)
+            return true;
+        if (obj == null)
+            return false;
+        if (getClass() != obj.getClass())
+            return false;
+        Policy that = Policy.class.cast(obj);
+        return Objects.equal(this.id, that.id);
+    }
+
+    @Override
+    public String toString() {
+        return Objects.toStringHelper(this).omitNullValues()
+                .add("id", id)
+                .add("src", src)
+                .add("srcType", srcType)
+                .add("srcPort", srcPort)
+                .add("dstService", dstService)
+                .add("dst", dst)
+                .add("dstType", dstType)
+                .add("dstPort", dstPort)
+                .add("protocol", protocol)
+                .add("action", action)
+                .add("log", log).toString();
+    }
+
+    @Override
+    public int compareTo(Policy o) {
+        return id - o.id;
+    }
+}
diff --git a/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/domain/Product.java b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/domain/Product.java
new file mode 100644
index 0000000..447f81e
--- /dev/null
+++ b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/domain/Product.java
@@ -0,0 +1,84 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.fujitsu.fgcp.domain;
+
+import javax.xml.bind.annotation.XmlElement;
+
+import com.google.common.base.Objects;
+
+/**
+ * Represents a product for which usage information can be queried.
+ * 
+ * @author Dies Koper
+ */
+public class Product {
+    @XmlElement(name = "productName")
+    private String name;
+
+    private String unitName;
+
+    private String usedPoints;
+
+    /**
+     * @return the name
+     */
+    public String getName() {
+        return name;
+    }
+
+    /**
+     * @return the unitName
+     */
+    public String getUnitName() {
+        return unitName;
+    }
+
+    /**
+     * @return the usedPoints
+     */
+    public String getUsedPoints() {
+        return usedPoints;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hashCode(name, unitName, usedPoints);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj)
+            return true;
+        if (obj == null)
+            return false;
+        if (getClass() != obj.getClass())
+            return false;
+        Product that = Product.class.cast(obj);
+        return Objects.equal(this.name, that.name)
+                && Objects.equal(this.unitName, that.unitName)
+                && Objects.equal(this.usedPoints, that.usedPoints);
+    }
+
+    @Override
+    public String toString() {
+        return Objects.toStringHelper(this).omitNullValues().add("name", name)
+                .add("unitName", unitName).add("usedPoints", usedPoints)
+                .toString();
+    }
+}
diff --git a/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/domain/PublicIP.java b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/domain/PublicIP.java
new file mode 100644
index 0000000..698c462
--- /dev/null
+++ b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/domain/PublicIP.java
@@ -0,0 +1,94 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.fujitsu.fgcp.domain;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import javax.xml.bind.annotation.XmlElement;
+
+import com.google.common.base.CaseFormat;
+import com.google.common.base.Objects;
+
+/**
+ * Represents a public IP address.
+ * <p>
+ * A public IP address can be allocated to a virtual system, then needs to be
+ * enabled/attached before it can be mapped to a virtual server by configuring
+ * the NAT settings of virtual system's firewall.
+ * 
+ * @author Dies Koper
+ */
+public class PublicIP {
+
+    public static enum Version {
+        IPv4, IPv6, UNRECOGNIZED;
+
+        @Override
+        public String toString() {
+            return CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.UPPER_CAMEL,
+                    name());
+        }
+
+        public static Version fromValue(String version) {
+            try {
+                return valueOf(CaseFormat.UPPER_CAMEL.to(
+                        CaseFormat.UPPER_UNDERSCORE,
+                        checkNotNull(version, "version")));
+            } catch (IllegalArgumentException e) {
+                return UNRECOGNIZED;
+            }
+        }
+
+    }
+
+    protected String address;
+    @XmlElement(name = "v4v6Flag")
+    protected Version version;
+
+    public String getAddress() {
+        return address;
+    }
+
+    public Version getVersion() {
+        return version;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hashCode(address);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj)
+            return true;
+        if (obj == null)
+            return false;
+        if (getClass() != obj.getClass())
+            return false;
+        PublicIP that = PublicIP.class.cast(obj);
+        return Objects.equal(this.address, that.address);
+    }
+
+    @Override
+    public String toString() {
+        return Objects.toStringHelper(this).omitNullValues()
+                .add("address", address).add("version", version).toString();
+    }
+}
\ No newline at end of file
diff --git a/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/domain/PublicIPStatus.java b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/domain/PublicIPStatus.java
new file mode 100644
index 0000000..3b10c95
--- /dev/null
+++ b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/domain/PublicIPStatus.java
@@ -0,0 +1,57 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.fujitsu.fgcp.domain;
+
+import javax.xml.bind.annotation.XmlRootElement;
+
+import com.google.common.base.CaseFormat;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * Possible statuses of a public IP address.
+ * <p>
+ * An attached public IP address is enabled for a particular virtual system and
+ * or may not be mapped to a virtual server.
+ * 
+ * @author Dies Koper
+ */
+@XmlRootElement(name = "publicipStatus")
+public enum PublicIPStatus {
+    ATTACHED, ATTACHING, DETACHING, DETACHED, UNRECOGNIZED;
+
+    public String value() {
+        return (CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.UPPER_CAMEL, name()));
+    }
+
+    @Override
+    public String toString() {
+        return value();
+    }
+
+    public static PublicIPStatus fromValue(String status) {
+        try {
+            return valueOf(CaseFormat.UPPER_CAMEL
+                    .to(CaseFormat.UPPER_UNDERSCORE,
+                            checkNotNull(status, "status")));
+        } catch (IllegalArgumentException e) {
+            return UNRECOGNIZED;
+        }
+    }
+}
diff --git a/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/domain/Rule.java b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/domain/Rule.java
new file mode 100644
index 0000000..6cd9798
--- /dev/null
+++ b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/domain/Rule.java
@@ -0,0 +1,84 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.fujitsu.fgcp.domain;
+
+import com.google.common.base.Objects;
+
+/**
+ * Represents a network address translation or network address port translation
+ * rule.
+ * <p>
+ * A rule either maps a public IP address to the NIC of a virtual server for
+ * incoming network traffic, or specifies the public IP address used as source
+ * address for traffic from all servers in the virtual system.
+ * 
+ * @author Dies Koper
+ */
+public class Rule {
+    private String publicIp;
+    private String privateIp;
+    private boolean snapt;
+
+    /**
+     * @return the publicIp
+     */
+    public String getPublicIp() {
+        return publicIp;
+    }
+
+    /**
+     * @return the privateIp
+     */
+    public String getPrivateIp() {
+        return privateIp;
+    }
+
+    /**
+     * @return the snapt
+     */
+    public boolean isSnapt() {
+        return snapt;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hashCode(privateIp, publicIp, snapt);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj)
+            return true;
+        if (obj == null)
+            return false;
+        if (getClass() != obj.getClass())
+            return false;
+        Rule that = Rule.class.cast(obj);
+        return Objects.equal(this.privateIp, that.privateIp)
+                && Objects.equal(this.publicIp, that.publicIp)
+                && Objects.equal(this.snapt, that.snapt);
+    }
+
+    @Override
+    public String toString() {
+        return Objects.toStringHelper(this).omitNullValues()
+                .add("privateIp", privateIp).add("publicIp", publicIp)
+                .add("snapt", snapt).toString();
+    }
+}
diff --git a/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/domain/SLB.java b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/domain/SLB.java
new file mode 100644
index 0000000..274c3b8
--- /dev/null
+++ b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/domain/SLB.java
@@ -0,0 +1,200 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.fujitsu.fgcp.domain;
+
+import java.util.LinkedHashSet;
+import java.util.Set;
+
+import javax.xml.bind.annotation.XmlRootElement;
+
+import com.google.common.collect.ImmutableSet;
+
+/**
+ * Represents a software load balancer.
+ * 
+ * @author Dies Koper
+ */
+@XmlRootElement(name = "slb")
+public class SLB extends BuiltinServer {
+    private String ipAddress;
+
+    private Set<IntermediateCACert> ccacerts = new LinkedHashSet<IntermediateCACert>();
+
+    private Set<ServerCert> servercerts = new LinkedHashSet<ServerCert>();
+
+    private Set<Group> groups;
+
+    private String srcType;
+
+    private String srcPort;
+
+    private String status;
+
+    private ErrorStatistics errorStatistics;
+
+    private LoadStatistics loadStatistics;
+
+    private String category;
+
+    private String latestVersion;
+
+    private String comment;
+
+    private boolean firmUpdateExist;
+
+    private boolean configUpdateExist;
+
+    private boolean backout;
+
+    private String updateDate;
+
+    private String currentVersion;
+
+    private String webAccelerator;
+
+    /**
+     * @return the ipAddress
+     */
+    public String getIpAddress() {
+        return ipAddress;
+    }
+
+    /**
+     * @return the ccacerts
+     */
+    public Set<IntermediateCACert> getCcacerts() {
+        return ccacerts == null ? ImmutableSet.<IntermediateCACert> of()
+                : ImmutableSet.copyOf(ccacerts);
+    }
+
+    /**
+     * @return the servercerts
+     */
+    public Set<ServerCert> getServercerts() {
+        return servercerts == null ? ImmutableSet.<ServerCert> of()
+                : ImmutableSet.copyOf(servercerts);
+    }
+
+    /**
+     * @return the groups
+     */
+    public Set<Group> getGroups() {
+        return groups == null ? ImmutableSet.<Group> of() : ImmutableSet
+                .copyOf(groups);
+    }
+
+    /**
+     * @return the srcType
+     */
+    public String getSrcType() {
+        return srcType;
+    }
+
+    /**
+     * @return the srcPort
+     */
+    public String getSrcPort() {
+        return srcPort;
+    }
+
+    /**
+     * @return the status
+     */
+    public String getStatus() {
+        return status;
+    }
+
+    /**
+     * @return the errorStatistics
+     */
+    public ErrorStatistics getErrorStatistics() {
+        return errorStatistics;
+    }
+
+    /**
+     * @return the loadStatistics
+     */
+    public LoadStatistics getLoadStatistics() {
+        return loadStatistics;
+    }
+
+    /**
+     * @return the category
+     */
+    public String getCategory() {
+        return category;
+    }
+
+    /**
+     * @return the latestVersion
+     */
+    public String getLatestVersion() {
+        return latestVersion;
+    }
+
+    /**
+     * @return the comment
+     */
+    public String getComment() {
+        return comment;
+    }
+
+    /**
+     * @return the firmUpdateExist
+     */
+    public boolean getFirmUpdateExist() {
+        return firmUpdateExist;
+    }
+
+    /**
+     * @return the configUpdateExist
+     */
+    public boolean getConfigUpdateExist() {
+        return configUpdateExist;
+    }
+
+    /**
+     * @return the backout
+     */
+    public boolean getBackout() {
+        return backout;
+    }
+
+    /**
+     * @return the updateDate
+     */
+    public String getUpdateDate() {
+        return updateDate;
+    }
+
+    /**
+     * @return the currentVersion
+     */
+    public String getCurrentVersion() {
+        return currentVersion;
+    }
+
+    /**
+     * @return the webAccelerator
+     */
+    public String getWebAccelerator() {
+        return webAccelerator;
+    }
+
+}
diff --git a/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/domain/ServerCert.java b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/domain/ServerCert.java
new file mode 100644
index 0000000..d1dfc06
--- /dev/null
+++ b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/domain/ServerCert.java
@@ -0,0 +1,121 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.fujitsu.fgcp.domain;
+
+import javax.xml.bind.annotation.XmlRootElement;
+
+import com.google.common.base.Objects;
+
+/**
+ * Describes a server certificate for use with a load balancer (SLB).
+ * 
+ * @author Dies Koper
+ */
+@XmlRootElement(name = "servercert")
+public class ServerCert implements Comparable<ServerCert> {
+    private int certNum;
+
+    private String subject;
+
+    private String issuer;
+
+    private String validity;
+
+    private int groupId;
+
+    private String detail;
+
+    /**
+     * @return the certNum
+     */
+    public int getCertNum() {
+        return certNum;
+    }
+
+    /**
+     * @return the subject
+     */
+    public String getSubject() {
+        return subject;
+    }
+
+    /**
+     * @return the issuer
+     */
+    public String getIssuer() {
+        return issuer;
+    }
+
+    /**
+     * @return the validity
+     */
+    public String getValidity() {
+        return validity;
+    }
+
+    /**
+     * @return the groupId
+     */
+    public int getGroupId() {
+        return groupId;
+    }
+
+    /**
+     * @return the detail
+     */
+    public String getDetail() {
+        return detail;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hashCode(certNum, groupId, issuer, subject, validity);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj)
+            return true;
+        if (obj == null)
+            return false;
+        if (getClass() != obj.getClass())
+            return false;
+        ServerCert that = ServerCert.class.cast(obj);
+        return Objects.equal(this.certNum, that.certNum)
+                && Objects.equal(this.groupId, that.groupId)
+                && Objects.equal(this.issuer, that.issuer)
+                && Objects.equal(this.subject, that.subject)
+                && Objects.equal(this.validity, that.validity);
+    }
+
+    @Override
+    public String toString() {
+        return Objects.toStringHelper(this).omitNullValues()
+                .add("certNum", certNum).add("issuer", issuer)
+                .add("subject", subject).add("validity", validity)
+                .add("groupId", groupId).add("detail", detail).toString();
+    }
+
+    @Override
+    public int compareTo(ServerCert o) {
+        return (certNum - o.certNum) == 0 ? (groupId - o.groupId)
+                : (certNum - o.certNum);
+    }
+
+}
diff --git a/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/domain/ServerType.java b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/domain/ServerType.java
new file mode 100644
index 0000000..b4a7248
--- /dev/null
+++ b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/domain/ServerType.java
@@ -0,0 +1,145 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.fujitsu.fgcp.domain;
+
+import java.util.Set;
+
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlElementWrapper;
+import javax.xml.bind.annotation.XmlRootElement;
+
+import com.google.common.base.Objects;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Sets;
+
+/**
+ * Describes the hardware of a virtual server.
+ * 
+ * @author Dies Koper
+ */
+@XmlRootElement(name = "servertype")
+public class ServerType implements Comparable<ServerType> {
+    private String id;
+
+    private String name;
+
+    private String label;
+
+    private String comment;
+
+    private String productId;
+
+    private String productName;
+
+    private String price;
+
+    private String chargeType;
+
+    private String expectedUsage;
+
+    private CPU cpu;
+
+    private Memory memory;
+
+    @XmlElementWrapper(name = "disks")
+    @XmlElement(name = "disk")
+    private Set<Disk> disks = Sets.newLinkedHashSet();
+
+    public String getId() {
+        return id;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public String getLabel() {
+        return label;
+    }
+
+    public String getComment() {
+        return comment;
+    }
+
+    public String getProductId() {
+        return productId;
+    }
+
+    public String getProductName() {
+        return productName;
+    }
+
+    public String getPrice() {
+        return price;
+    }
+
+    public String getChargeType() {
+        return chargeType;
+    }
+
+    public String getExpectedUsage() {
+        return expectedUsage;
+    }
+
+    public CPU getCpu() {
+        return cpu;
+    }
+
+    public Memory getMemory() {
+        return memory;
+    }
+
+    public Set<Disk> getDisks() {
+        return disks == null ? ImmutableSet.<Disk> of() : ImmutableSet
+                .copyOf(disks);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hashCode(id);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj)
+            return true;
+        if (obj == null)
+            return false;
+        if (getClass() != obj.getClass())
+            return false;
+        ServerType that = ServerType.class.cast(obj);
+        return Objects.equal(this.id, that.id);
+    }
+
+    @Override
+    public String toString() {
+        return Objects.toStringHelper(this).omitNullValues().add("id", id)
+                .add("name", name).add("label", label).add("comment", comment)
+                .add("productId", productId).add("productName", productName)
+                .add("price", price).add("chargeType", chargeType)
+                .add("expectedUsage", expectedUsage).add("cpu", cpu)
+                .add("memory", memory).add("disks", disks).toString();
+    }
+
+    @Override
+    public int compareTo(ServerType o) {
+        return memory == null ? -1 : memory.compareTo(o.memory);
+    }
+
+}
diff --git a/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/domain/Software.java b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/domain/Software.java
new file mode 100644
index 0000000..cfff2a6
--- /dev/null
+++ b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/domain/Software.java
@@ -0,0 +1,103 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.fujitsu.fgcp.domain;
+
+import com.google.common.base.Objects;
+
+/**
+ * Represents the software installed on a disk.
+ * 
+ * @author Dies Koper
+ */
+public class Software {
+    private String name;
+
+    private String id;
+
+    private String category;
+
+    private String version;
+
+    private String officialVersion;
+
+    private String patch;
+
+    private String license;
+
+    private String support;
+
+    public String getName() {
+        return name;
+    }
+
+    public String getId() {
+        return id;
+    }
+
+    public String getCategory() {
+        return category;
+    }
+
+    public String getVersion() {
+        return version;
+    }
+
+    public String getOfficialVersion() {
+        return officialVersion;
+    }
+
+    public String getPatch() {
+        return patch;
+    }
+
+    public String getLicense() {
+        return license;
+    }
+
+    public String getSupport() {
+        return support;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hashCode(id);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj)
+            return true;
+        if (obj == null)
+            return false;
+        if (getClass() != obj.getClass())
+            return false;
+        Software that = Software.class.cast(obj);
+        return Objects.equal(this.id, that.id);
+    }
+
+    @Override
+    public String toString() {
+        return Objects.toStringHelper(this).omitNullValues().add("id", id)
+                .add("name", name).add("category", category)
+                .add("version", version)
+                .add("officialVersion", officialVersion)
+                .add("support", support).add("patch", patch)
+                .add("license", license).toString();
+    }
+}
diff --git a/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/domain/Target.java b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/domain/Target.java
new file mode 100644
index 0000000..44cd0fe
--- /dev/null
+++ b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/domain/Target.java
@@ -0,0 +1,126 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.fujitsu.fgcp.domain;
+
+import com.google.common.base.Objects;
+
+/**
+ * Describes the target server of a load balancer.
+ * 
+ * @author Dies Koper
+ */
+public class Target {
+    private String serverId;
+
+    private String serverName;
+
+    private String ipAddress;
+
+    private String port1;
+
+    private String port2;
+
+    private String status;
+
+    private String now;
+
+    private String peak;
+
+    /**
+     * @return the serverId
+     */
+    public String getServerId() {
+        return serverId;
+    }
+
+    /**
+     * @return the serverName
+     */
+    public String getServerName() {
+        return serverName;
+    }
+
+    /**
+     * @return the ipAddress
+     */
+    public String getIpAddress() {
+        return ipAddress;
+    }
+
+    /**
+     * @return the port1
+     */
+    public String getPort1() {
+        return port1;
+    }
+
+    /**
+     * @return the port2
+     */
+    public String getPort2() {
+        return port2;
+    }
+
+    /**
+     * @return the status
+     */
+    public String getStatus() {
+        return status;
+    }
+
+    /**
+     * @return the now
+     */
+    public String getNow() {
+        return now;
+    }
+
+    /**
+     * @return the peak
+     */
+    public String getPeak() {
+        return peak;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hashCode(serverId);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj)
+            return true;
+        if (obj == null)
+            return false;
+        if (getClass() != obj.getClass())
+            return false;
+        Target that = Target.class.cast(obj);
+        return Objects.equal(this.serverId, that.serverId);
+    }
+
+    @Override
+    public String toString() {
+        return Objects.toStringHelper(this).omitNullValues()
+                .add("serverId", serverId).add("serverName", serverName)
+                .add("ipAddress", ipAddress).add("port1", port1)
+                .add("port2", port2).add("status", status).add("now", now)
+                .add("peak", peak).toString();
+    }
+}
diff --git a/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/domain/UsageInfo.java b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/domain/UsageInfo.java
new file mode 100644
index 0000000..48cffa4
--- /dev/null
+++ b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/domain/UsageInfo.java
@@ -0,0 +1,94 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.fujitsu.fgcp.domain;
+
+import java.util.LinkedHashSet;
+import java.util.Set;
+
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlElementWrapper;
+import javax.xml.bind.annotation.XmlRootElement;
+
+import com.google.common.base.Objects;
+import com.google.common.collect.ImmutableSet;
+
+/**
+ * Describes the usage by a virtual system.
+ * 
+ * @author Dies Koper
+ */
+@XmlRootElement(name = "usageinfo")
+public class UsageInfo {
+    @XmlElement(name = "vsysId")
+    private String systemId;
+    @XmlElement(name = "vsysName")
+    private String systemName;
+
+    @XmlElementWrapper(name = "products")
+    @XmlElement(name = "product")
+    private Set<Product> products = new LinkedHashSet<Product>();
+
+    /**
+     * @return the systemId
+     */
+    public String getSystemId() {
+        return systemId;
+    }
+
+    /**
+     * @return the systemName
+     */
+    public String getSystemName() {
+        return systemName;
+    }
+
+    /**
+     * @return the products
+     */
+    public Set<Product> getProducts() {
+        return products == null ? ImmutableSet.<Product> of() : ImmutableSet
+                .copyOf(products);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hashCode(systemId, systemName, products);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj)
+            return true;
+        if (obj == null)
+            return false;
+        if (getClass() != obj.getClass())
+            return false;
+        UsageInfo that = UsageInfo.class.cast(obj);
+        return Objects.equal(this.systemId, that.systemId)
+                && Objects.equal(this.systemName, that.systemName)
+                && Objects.equal(this.products, that.products);
+    }
+
+    @Override
+    public String toString() {
+        return Objects.toStringHelper(this).omitNullValues()
+                .add("systemId", systemId).add("systemName", systemName)
+                .add("products", products).toString();
+    }
+}
diff --git a/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/domain/VDisk.java b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/domain/VDisk.java
new file mode 100644
index 0000000..e8784c4
--- /dev/null
+++ b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/domain/VDisk.java
@@ -0,0 +1,86 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.fujitsu.fgcp.domain;
+
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+
+import com.google.common.base.Objects;
+
+/**
+ * Represents attachable storage in the form of a virtual disk.
+ * 
+ * @author Dies Koper
+ */
+@XmlRootElement(name = "vdisk")
+public class VDisk {
+    @XmlElement(name = "diskId")
+    private String id;
+    @XmlElement(name = "diskName")
+    private String name;
+    @XmlElement(name = "attachedTo")
+    private String attachedServer;
+    private String creator;
+    private double size;
+
+    public String getId() {
+        return id;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public String getAttachedServer() {
+        return attachedServer;
+    }
+
+    public String getCreator() {
+        return creator;
+    }
+
+    public double getSize() {
+        return size;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hashCode(id);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj)
+            return true;
+        if (obj == null)
+            return false;
+        if (getClass() != obj.getClass())
+            return false;
+        VDisk that = VDisk.class.cast(obj);
+        return Objects.equal(this.id, that.id);
+    }
+
+    @Override
+    public String toString() {
+        return Objects.toStringHelper(this).omitNullValues().add("id", id)
+                .add("name", name).add("attachedServer", attachedServer)
+                .add("creator", creator).add("size", size).toString();
+    }
+
+}
diff --git a/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/domain/VDiskStatus.java b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/domain/VDiskStatus.java
new file mode 100644
index 0000000..cc44594
--- /dev/null
+++ b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/domain/VDiskStatus.java
@@ -0,0 +1,55 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.fujitsu.fgcp.domain;
+
+import javax.xml.bind.annotation.XmlRootElement;
+
+import com.google.common.base.CaseFormat;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * Possible statuses of an attachable virtual disk.
+ * 
+ * @author Dies Koper
+ */
+@XmlRootElement(name = "vdiskStatus")
+public enum VDiskStatus {
+
+    NORMAL, BACKUP_ING, DEPLOYING, DETACHING, ATTACHING, RESTORING, ERROR, UNRECOGNIZED;
+
+    public String value() {
+        return (CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.UPPER_CAMEL, name()));
+    }
+
+    @Override
+    public String toString() {
+        return value();
+    }
+
+    public static VDiskStatus fromValue(String status) {
+        try {
+            return valueOf(CaseFormat.UPPER_CAMEL
+                    .to(CaseFormat.UPPER_UNDERSCORE,
+                            checkNotNull(status, "status")));
+        } catch (IllegalArgumentException e) {
+            return UNRECOGNIZED;
+        }
+    }
+}
\ No newline at end of file
diff --git a/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/domain/VNIC.java b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/domain/VNIC.java
new file mode 100644
index 0000000..6fbf077
--- /dev/null
+++ b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/domain/VNIC.java
@@ -0,0 +1,73 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.fujitsu.fgcp.domain;
+
+import javax.xml.bind.annotation.XmlRootElement;
+
+import com.google.common.base.Objects;
+
+/**
+ * Represents a virtual network interface card (NIC).
+ * 
+ * @author Dies Koper
+ */
+@XmlRootElement(name = "vnic")
+public class VNIC {
+    private String networkId;
+
+    private String privateIp;
+
+    private int nicNo;
+
+    public String getNetworkId() {
+        return networkId;
+    }
+
+    public String getPrivateIp() {
+        return privateIp;
+    }
+
+    public int getNicNo() {
+        return nicNo;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hashCode(networkId);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj)
+            return true;
+        if (obj == null)
+            return false;
+        if (getClass() != obj.getClass())
+            return false;
+        VNIC that = VNIC.class.cast(obj);
+        return Objects.equal(this.networkId, that.networkId);
+    }
+
+    @Override
+    public String toString() {
+        return Objects.toStringHelper(this).omitNullValues()
+                .add("networkId", networkId).add("privateIp", privateIp)
+                .add("nicNo", nicNo).toString();
+    }
+}
diff --git a/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/domain/VNet.java b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/domain/VNet.java
new file mode 100644
index 0000000..77210c1
--- /dev/null
+++ b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/domain/VNet.java
@@ -0,0 +1,61 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.fujitsu.fgcp.domain;
+
+import javax.xml.bind.annotation.XmlRootElement;
+
+import com.google.common.base.Objects;
+
+/**
+ * Represents a virtual network.
+ * 
+ * @author Dies Koper
+ */
+@XmlRootElement(name = "vnet")
+public class VNet {
+
+    private String networkId;
+
+    public String getNetworkId() {
+        return networkId;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hashCode(networkId);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj)
+            return true;
+        if (obj == null)
+            return false;
+        if (getClass() != obj.getClass())
+            return false;
+        VNet that = VNet.class.cast(obj);
+        return Objects.equal(this.networkId, that.networkId);
+    }
+
+    @Override
+    public String toString() {
+        return Objects.toStringHelper(this).add("networkId", networkId)
+                .toString();
+    }
+}
diff --git a/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/domain/VServer.java b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/domain/VServer.java
new file mode 100644
index 0000000..b3db299
--- /dev/null
+++ b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/domain/VServer.java
@@ -0,0 +1,84 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.fujitsu.fgcp.domain;
+
+import javax.xml.bind.annotation.XmlElement;
+
+import com.google.common.base.Objects;
+
+/**
+ * Represents a virtual server.
+ * 
+ * @author Dies Koper
+ */
+public class VServer {
+    @XmlElement(name = "vserverId")
+    protected String id;
+    @XmlElement(name = "vserverName")
+    protected String name;
+    @XmlElement(name = "vserverType")
+    protected String type;
+    protected String diskimageId;
+    protected String creator;
+
+    public String getId() {
+        return id;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public String getType() {
+        return type;
+    }
+
+    public String getDiskimageId() {
+        return diskimageId;
+    }
+
+    public String getCreator() {
+        return creator;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hashCode(id);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj)
+            return true;
+        if (obj == null)
+            return false;
+        if (getClass() != obj.getClass())
+            return false;
+        VServer that = VServer.class.cast(obj);
+        return Objects.equal(this.id, that.id);
+    }
+
+    @Override
+    public String toString() {
+        return Objects.toStringHelper(this).omitNullValues().add("id", id)
+                .add("name", name).add("type", type).add("creator", creator)
+                .add("diskimageId", diskimageId).toString();
+    }
+
+}
\ No newline at end of file
diff --git a/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/domain/VServerStatus.java b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/domain/VServerStatus.java
new file mode 100644
index 0000000..8576538
--- /dev/null
+++ b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/domain/VServerStatus.java
@@ -0,0 +1,54 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.fujitsu.fgcp.domain;
+
+import javax.xml.bind.annotation.XmlRootElement;
+
+import com.google.common.base.CaseFormat;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * Possible statuses of a virtual server.
+ * 
+ * @author Dies Koper
+ */
+@XmlRootElement(name = "vserverStatus")
+public enum VServerStatus {
+    DEPLOYING, RUNNING, STOPPING, STOPPED, STARTING, FAILOVER, UNEXPECTED_STOP, RESTORING, BACKUP_ING, ERROR, START_ERROR, STOP_ERROR, CHANGE_TYPE, REGISTERING, UNRECOGNIZED;
+
+    public String value() {
+        return (CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.UPPER_CAMEL, name()));
+    }
+
+    @Override
+    public String toString() {
+        return value();
+    }
+
+    public static VServerStatus fromValue(String status) {
+        try {
+            return valueOf(CaseFormat.UPPER_CAMEL
+                    .to(CaseFormat.UPPER_UNDERSCORE,
+                            checkNotNull(status, "status")));
+        } catch (IllegalArgumentException e) {
+            return UNRECOGNIZED;
+        }
+    }
+}
diff --git a/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/domain/VServerWithDetails.java b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/domain/VServerWithDetails.java
new file mode 100644
index 0000000..d9613a4
--- /dev/null
+++ b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/domain/VServerWithDetails.java
@@ -0,0 +1,59 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.fujitsu.fgcp.domain;
+
+import java.util.LinkedHashSet;
+import java.util.Set;
+
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlElementWrapper;
+import javax.xml.bind.annotation.XmlRootElement;
+
+import com.google.common.base.Objects;
+import com.google.common.collect.ImmutableSet;
+
+/**
+ * Represents a virtual server with virtual storage and NICs.
+ * 
+ * @author Dies Koper
+ */
+@XmlRootElement(name = "vserver")
+public class VServerWithDetails extends VServerWithVNICs {
+    @XmlElementWrapper(name = "vdisks")
+    @XmlElement(name = "vdisk")
+    protected Set<VDisk> vdisks = new LinkedHashSet<VDisk>();
+    protected Image image;
+
+    public Set<VDisk> getVdisks() {
+        return vdisks == null ? ImmutableSet.<VDisk> of() : ImmutableSet
+                .copyOf(vdisks);
+    }
+
+    public Image getImage() {
+        return image;
+    }
+
+    @Override
+    public String toString() {
+        return Objects.toStringHelper(this).omitNullValues().add("id", id)
+                .add("name", name).add("type", type).add("creator", creator)
+                .add("diskimageId", diskimageId).add("vdisks", vdisks)
+                .add("vnics", vnics).add("image", image).toString();
+    }
+}
diff --git a/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/domain/VServerWithVNICs.java b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/domain/VServerWithVNICs.java
new file mode 100644
index 0000000..3117241
--- /dev/null
+++ b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/domain/VServerWithVNICs.java
@@ -0,0 +1,29 @@
+package org.jclouds.fujitsu.fgcp.domain;
+
+import java.util.LinkedHashSet;
+import java.util.Set;
+
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlElementWrapper;
+
+import com.google.common.base.Objects;
+import com.google.common.collect.ImmutableSet;
+
+public class VServerWithVNICs extends VServer {
+
+    @XmlElementWrapper(name = "vnics")
+    @XmlElement(name = "vnic")
+    protected Set<VNIC> vnics = new LinkedHashSet<VNIC>();
+
+    public Set<VNIC> getVnics() {
+        return vnics == null ? ImmutableSet.<VNIC> of() : ImmutableSet
+                .copyOf(vnics);
+    }
+
+    @Override
+    public String toString() {
+        return Objects.toStringHelper(this).omitNullValues().add("id", id)
+                .add("name", name).add("type", type).add("creator", creator)
+                .add("diskimageId", diskimageId).add("vnics", vnics).toString();
+    }
+}
\ No newline at end of file
diff --git a/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/domain/VSystem.java b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/domain/VSystem.java
new file mode 100644
index 0000000..ae86034
--- /dev/null
+++ b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/domain/VSystem.java
@@ -0,0 +1,84 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.fujitsu.fgcp.domain;
+
+import javax.xml.bind.annotation.XmlElement;
+
+import com.google.common.base.Objects;
+
+/**
+ * Represents a virtual system.
+ * 
+ * @author Dies Koper
+ */
+public class VSystem {
+    @XmlElement(name = "vsysId")
+    protected String id;
+    @XmlElement(name = "vsysName")
+    protected String name;
+    protected String creator;
+    @XmlElement(name = "baseDescriptor")
+    protected String template;
+    protected String description;
+
+    public String getId() {
+        return id;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public String getCreator() {
+        return creator;
+    }
+
+    public String getTemplate() {
+        return template;
+    }
+
+    public String getDescription() {
+        return description;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hashCode(id);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj)
+            return true;
+        if (obj == null)
+            return false;
+        if (getClass() != obj.getClass())
+            return false;
+        VSystem that = VSystem.class.cast(obj);
+        return Objects.equal(this.id, that.id);
+    }
+
+    @Override
+    public String toString() {
+        return Objects.toStringHelper(this).omitNullValues().add("id", id)
+                .add("name", name).add("creator", creator)
+                .add("template", template).add("description", description)
+                .toString();
+    }
+}
diff --git a/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/domain/VSystemDescriptor.java b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/domain/VSystemDescriptor.java
new file mode 100644
index 0000000..46f448a
--- /dev/null
+++ b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/domain/VSystemDescriptor.java
@@ -0,0 +1,104 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.fujitsu.fgcp.domain;
+
+import java.util.LinkedHashSet;
+import java.util.Set;
+
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlElementWrapper;
+import javax.xml.bind.annotation.XmlRootElement;
+
+import com.google.common.collect.ImmutableSet;
+
+/**
+ * Describes a virtual system template.
+ * 
+ * @author Dies Koper
+ */
+@XmlRootElement(name = "vsysdescriptor")
+public class VSystemDescriptor {
+    @XmlElement(name = "vsysdescriptorId")
+    private String id;
+
+    @XmlElement(name = "vsysdescriptorName")
+    private String name;
+
+    private String creatorName;
+
+    private String registrant;
+
+    private String description;
+
+    private String keyword;
+
+    @XmlElementWrapper(name = "vservers")
+    @XmlElement(name = "vserver")
+    private Set<VServerWithDetails> servers = new LinkedHashSet<VServerWithDetails>();
+
+    /**
+     * @return the id
+     */
+    public String getId() {
+        return id;
+    }
+
+    /**
+     * @return the name
+     */
+    public String getName() {
+        return name;
+    }
+
+    /**
+     * @return the creatorName
+     */
+    public String getCreatorName() {
+        return creatorName;
+    }
+
+    /**
+     * @return the registrant
+     */
+    public String getRegistrant() {
+        return registrant;
+    }
+
+    /**
+     * @return the description
+     */
+    public String getDescription() {
+        return description;
+    }
+
+    /**
+     * @return the keyword
+     */
+    public String getKeyword() {
+        return keyword;
+    }
+
+    /**
+     * @return the servers
+     */
+    public Set<VServerWithDetails> getServers() {
+        return servers == null ? ImmutableSet.<VServerWithDetails> of()
+                : ImmutableSet.copyOf(servers);
+    }
+}
diff --git a/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/domain/VSystemStatus.java b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/domain/VSystemStatus.java
new file mode 100644
index 0000000..58e6e7a
--- /dev/null
+++ b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/domain/VSystemStatus.java
@@ -0,0 +1,54 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.fujitsu.fgcp.domain;
+
+import javax.xml.bind.annotation.XmlRootElement;
+
+import com.google.common.base.CaseFormat;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * Possible statuses of a virtual system.
+ * 
+ * @author Dies Koper
+ */
+@XmlRootElement(name = "vsysStatus")
+public enum VSystemStatus {
+    NORMAL, RECONFIG_ING, DEPLOYING, ERROR, UNRECOGNIZED;
+
+    public String value() {
+        return (CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.UPPER_CAMEL, name()));
+    }
+
+    @Override
+    public String toString() {
+        return value();
+    }
+
+    public static VSystemStatus fromValue(String status) {
+        try {
+            return valueOf(CaseFormat.UPPER_CAMEL
+                    .to(CaseFormat.UPPER_UNDERSCORE,
+                            checkNotNull(status, "status")));
+        } catch (IllegalArgumentException e) {
+            return UNRECOGNIZED;
+        }
+    }
+}
diff --git a/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/domain/VSystemWithDetails.java b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/domain/VSystemWithDetails.java
new file mode 100644
index 0000000..1683988
--- /dev/null
+++ b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/domain/VSystemWithDetails.java
@@ -0,0 +1,80 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.fujitsu.fgcp.domain;
+
+import java.util.LinkedHashSet;
+import java.util.Set;
+
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlElementWrapper;
+import javax.xml.bind.annotation.XmlRootElement;
+
+import com.google.common.base.Objects;
+import com.google.common.collect.ImmutableSet;
+
+/**
+ * Represents a virtual system with servers, additional storage, public IP
+ * addresses and networks.
+ * 
+ * @author Dies Koper
+ */
+@XmlRootElement(name = "vsys")
+public class VSystemWithDetails extends VSystem {
+    @XmlElementWrapper(name = "vservers")
+    @XmlElement(name = "vserver")
+    private Set<VServerWithVNICs> servers = new LinkedHashSet<VServerWithVNICs>();
+    @XmlElementWrapper(name = "vdisks")
+    @XmlElement(name = "vdisk")
+    private Set<VDisk> disks = new LinkedHashSet<VDisk>();
+    @XmlElementWrapper(name = "publicips")
+    @XmlElement(name = "publicip")
+    private Set<PublicIP> publicips = new LinkedHashSet<PublicIP>();
+    @XmlElementWrapper(name = "vnets")
+    @XmlElement(name = "vnet")
+    private Set<VNet> networks = new LinkedHashSet<VNet>();
+
+    public Set<VServerWithVNICs> getServers() {
+        return servers == null ? ImmutableSet.<VServerWithVNICs> of() : ImmutableSet
+                .copyOf(servers);
+    }
+
+    public Set<VDisk> getDisks() {
+        return disks == null ? ImmutableSet.<VDisk> of() : ImmutableSet
+                .copyOf(disks);
+    }
+
+    public Set<PublicIP> getPublicips() {
+        return publicips == null ? ImmutableSet.<PublicIP> of() : ImmutableSet
+                .copyOf(publicips);
+    }
+
+    public Set<VNet> getNetworks() {
+        return networks == null ? ImmutableSet.<VNet> of() : ImmutableSet
+                .copyOf(networks);
+    }
+
+    @Override
+    public String toString() {
+        return Objects.toStringHelper(this).omitNullValues().add("id", id)
+                .add("name", name).add("creator", creator)
+                .add("template", template).add("description", description)
+                .add("disks", disks).add("networks", networks)
+                .add("publicips", publicips).add("servers", servers).toString();
+    }
+}
diff --git a/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/domain/package-info.java b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/domain/package-info.java
new file mode 100644
index 0000000..4f79fc1
--- /dev/null
+++ b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/domain/package-info.java
@@ -0,0 +1,26 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+@XmlSchema(namespace = "http://apioviss.jp.fujitsu.com", elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED)
+@XmlAccessorType(XmlAccessType.FIELD)
+package org.jclouds.fujitsu.fgcp.domain;
+
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlSchema;
+
diff --git a/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/filters/RequestAuthenticator.java b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/filters/RequestAuthenticator.java
new file mode 100644
index 0000000..9fecf69
--- /dev/null
+++ b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/filters/RequestAuthenticator.java
@@ -0,0 +1,242 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.fujitsu.fgcp.filters;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.io.UnsupportedEncodingException;
+import java.security.InvalidKeyException;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.PrivateKey;
+import java.security.Signature;
+import java.security.UnrecoverableKeyException;
+import java.util.Calendar;
+import java.util.Locale;
+
+import javax.annotation.Resource;
+import javax.inject.Inject;
+import javax.inject.Named;
+import javax.inject.Provider;
+import javax.inject.Singleton;
+import javax.ws.rs.HttpMethod;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.UriBuilder;
+
+import org.jclouds.Constants;
+import org.jclouds.crypto.CryptoStreams;
+import org.jclouds.date.TimeStamp;
+import org.jclouds.encryption.internal.Base64;
+import org.jclouds.fujitsu.fgcp.reference.RequestParameters;
+import org.jclouds.http.HttpException;
+import org.jclouds.http.HttpRequest;
+import org.jclouds.http.HttpRequestFilter;
+import org.jclouds.http.HttpUtils;
+import org.jclouds.http.internal.SignatureWire;
+import org.jclouds.http.utils.Queries;
+import org.jclouds.logging.Logger;
+import org.jclouds.rest.RequestSigner;
+import org.jclouds.rest.annotations.ApiVersion;
+import org.jclouds.rest.annotations.Credential;
+
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.collect.Multimap;
+
+/**
+ * Generates and signs the access key id and adds the mandatory http header and
+ * request parameters to the request.
+ * 
+ * @author Dies Koper
+ */
+@Singleton
+public class RequestAuthenticator implements HttpRequestFilter, RequestSigner {
+
+    @Resource
+    @Named(Constants.LOGGER_SIGNATURE)
+    private Logger signatureLog = Logger.NULL;
+
+    final Provider<Calendar> calendarProvider;
+    final Signature signer;
+    final Provider<UriBuilder> builder;
+    final String apiVersion;
+
+    public String signatureVersion = "1.0";
+    public String signatureMethod = "SHA1withRSA";
+
+    private HttpUtils utils;
+
+    @Inject
+    public RequestAuthenticator(@TimeStamp Provider<Calendar> calendarProvider,
+            Provider<KeyStore> keyStoreProvider,
+            @Credential String keyPassword, Provider<UriBuilder> builder,
+            HttpUtils utils, SignatureWire signatureWire,
+            @ApiVersion String apiVersion) throws NoSuchAlgorithmException,
+            InvalidKeyException, KeyStoreException, UnrecoverableKeyException {
+        this.calendarProvider = checkNotNull(calendarProvider);
+        this.builder = checkNotNull(builder);
+        this.utils = checkNotNull(utils, "utils");
+        this.apiVersion = checkNotNull(apiVersion, "apiVersion");
+
+        signer = Signature.getInstance(signatureMethod);
+
+        KeyStore keyStore = checkNotNull(keyStoreProvider).get();
+        String alias = keyStore.aliases().nextElement(); // there should be only
+                                                         // one private key
+        PrivateKey privateKey = (PrivateKey) keyStore.getKey(alias,
+                keyPassword.toCharArray());
+
+        signer.initSign(privateKey);
+    }
+
+    public HttpRequest filter(HttpRequest request) throws HttpException {
+        checkNotNull(request, "request must be present");
+
+        utils.logRequest(signatureLog, request, ">>");
+
+        // create accesskeyid
+        String accessKeyId = createStringToSign(request);
+        String signature = sign(accessKeyId);
+
+        // leaving this in for now for reference in case I need it for multipart
+        // POSTs
+        // add parameters. Note that in case of a GET, url escaping is required
+        /*
+         * Multimap<String, String> decodedParams = null; if
+         * (HttpMethod.GET.equals(request.getMethod())) { decodedParams =
+         * ModifyRequest.parseQueryToMap(request.getEndpoint().getRawQuery());
+         * 
+         * } else if (HttpMethod.POST.equals(request.getMethod())) {
+         * decodedParams =
+         * ModifyRequest.parseQueryToMap(request.getPayload().getRawContent()
+         * .toString()); }
+         * 
+         * checkNotNull(decodedParams, "no query params found");
+         * System.out.println("filter: request params before: " +
+         * decodedParams.toString()); addAuthenticationParams(decodedParams,
+         * accessKeyId, signature); addLocaleParam(decodedParams);
+         * System.out.println("filter: request params after : " +
+         * decodedParams.toString()); if (signatureWire.enabled())
+         * signatureWire.output(decodedParams);
+         * 
+         * 
+         * request = setPayload(request, decodedParams);
+         */
+        // only "en" and "ja" are allowed
+        String lang = Locale.JAPANESE.getLanguage().equals(
+                Locale.getDefault().getLanguage()) ? Locale.JAPANESE
+                .getLanguage() : Locale.ENGLISH.getLanguage();
+
+        if (HttpMethod.GET.equals(request.getMethod())) {
+            Multimap<String, String> decodedParams = Queries
+                    .parseQueryToMap(request.getEndpoint().getRawQuery());
+
+            if (!decodedParams.containsKey(RequestParameters.VERSION)) {
+                decodedParams.put(RequestParameters.VERSION, apiVersion);
+            }
+            decodedParams.put(RequestParameters.LOCALE, lang);
+            decodedParams.put(RequestParameters.ACCESS_KEY_ID, accessKeyId);
+            decodedParams.put(RequestParameters.SIGNATURE, signature);
+            request = request.toBuilder().replaceQueryParams(decodedParams)
+                    .build();
+        } else {
+
+            String payload = request.getPayload().getRawContent().toString();
+            payload = createXmlElementWithValue(payload,
+                    RequestParameters.VERSION, apiVersion);
+            payload = createXmlElementWithValue(payload,
+                    RequestParameters.LOCALE, lang);
+            payload = createXmlElementWithValue(payload,
+                    RequestParameters.ACCESS_KEY_ID, accessKeyId);
+            payload = createXmlElementWithValue(payload,
+                    RequestParameters.SIGNATURE, signature);
+
+            // ensure there are no other query params left
+            request.setPayload(payload);
+            request.getPayload().getContentMetadata()
+                    .setContentType(MediaType.TEXT_XML);
+        }
+
+        // may need to do this elsewhere (see ConvertToGaeRequest)
+        HttpRequest filteredRequest = request.toBuilder()
+                .replaceHeader(HttpHeaders.USER_AGENT, "OViSS-API-CLIENT")
+                .build();
+
+        utils.logRequest(signatureLog, filteredRequest, ">>->");
+
+        return filteredRequest;
+    }
+
+    String createXmlElementWithValue(String payload, String tag, String value) {
+        String startTag = String.format("<%s>", tag);
+        String endTag = String.format("</%s>", tag);
+
+        return payload.replace(startTag + endTag, startTag + value + endTag);
+    }
+
+    /*
+     * HttpRequest setPayload(HttpRequest request, Multimap<String, String>
+     * decodedParams) {
+     * request.setPayload(ModifyRequest.makeQueryLine(decodedParams, null)); //
+     * request.getPayload().getContentMetadata().setContentType(
+     * "application/x-www-form-urlencoded"); return request; }
+     */
+
+    @VisibleForTesting
+    public String sign(String stringToSign) {
+        String signed;
+
+        try {
+            signer.update(stringToSign.getBytes("UTF-8"));
+            signed = Base64.encodeBytes(signer.sign()).replace("\n", "\r\n");
+//            signed = CryptoStreams.base64(signer.sign());
+        } catch (Exception e) {
+            throw new HttpException("error signing request", e);
+        }
+        // if (signatureWire.enabled())
+        // signatureWire.input(Strings2.toInputStream(signed));
+
+        return signed;
+    }
+
+    @VisibleForTesting
+    public String generateAccessKeyId() {
+        Calendar cal = calendarProvider.get();
+        String timezone = cal.getTimeZone().getDisplayName(Locale.ENGLISH);
+        String expires = String.valueOf(cal.getTime().getTime());
+
+        String signatureData = String.format("%s&%s&%s&%s", timezone, expires,
+                signatureVersion, signatureMethod);
+        try {
+            String accessKeyId = Base64.encodeBytes(signatureData.getBytes("UTF-8"));
+            return accessKeyId.replace("\n", "\r\n");
+//            return CryptoStreams.base64(signatureData.getBytes("UTF-8")).;
+        } catch (UnsupportedEncodingException e) {
+            throw new RuntimeException(e); // should never happen as
+                                           // signatureData contains only ASCII
+        }
+    }
+
+    @Override
+    public String createStringToSign(HttpRequest input) {
+        return generateAccessKeyId();
+    }
+
+}
diff --git a/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/handlers/FGCPRetryIfNotProxyAuthenticationFailureHandler.java b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/handlers/FGCPRetryIfNotProxyAuthenticationFailureHandler.java
new file mode 100644
index 0000000..0104aaf
--- /dev/null
+++ b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/handlers/FGCPRetryIfNotProxyAuthenticationFailureHandler.java
@@ -0,0 +1,47 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.fujitsu.fgcp.handlers;
+
+import com.google.inject.Singleton;
+import org.jclouds.http.HttpCommand;
+import org.jclouds.http.HttpResponse;
+import org.jclouds.http.HttpRetryHandler;
+import org.jclouds.logging.Logger;
+
+import javax.annotation.Resource;
+
+/**
+ * Created by IntelliJ IDEA.
+ * 
+ * @author Dies Koper
+ */
+@Singleton
+public class FGCPRetryIfNotProxyAuthenticationFailureHandler implements
+        HttpRetryHandler {
+    @Resource
+    protected Logger logger = Logger.NULL;
+
+    @Override
+    public boolean shouldRetryRequest(HttpCommand command, HttpResponse response) {
+        int statusCode = response.getStatusCode();
+        System.out.println("Response status code: " + statusCode);
+        logger.error("StatusCode", statusCode);
+        return true;
+    }
+}
diff --git a/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/http/SSLContextWithKeysSupplier.java b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/http/SSLContextWithKeysSupplier.java
new file mode 100644
index 0000000..c0e2019
--- /dev/null
+++ b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/http/SSLContextWithKeysSupplier.java
@@ -0,0 +1,71 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.fujitsu.fgcp.http;
+
+import java.security.KeyManagementException;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.SecureRandom;
+import java.security.UnrecoverableKeyException;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+import javax.net.ssl.KeyManagerFactory;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.TrustManager;
+
+import org.jclouds.http.HttpUtils;
+import org.jclouds.http.config.SSLModule.TrustAllCerts;
+import org.jclouds.rest.annotations.Credential;
+
+import com.google.common.base.Supplier;
+
+/**
+ * SSLContext supplier with a configured key manager to enable client
+ * authentication with certificates.
+ * 
+ * @author Dies Koper
+ */
+@Singleton
+public class SSLContextWithKeysSupplier implements Supplier<SSLContext> {
+    private SSLContext sc;
+
+    @Inject
+    SSLContextWithKeysSupplier(KeyStore keyStore,
+            @Credential String keyStorePassword, HttpUtils utils,
+            TrustAllCerts trustAllCerts) throws NoSuchAlgorithmException,
+            KeyStoreException, UnrecoverableKeyException,
+            KeyManagementException {
+
+        TrustManager[] trustManager = null;
+        if (utils.trustAllCerts()) {
+            trustManager = new TrustManager[] { trustAllCerts };
+        }
+        KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
+        kmf.init(keyStore, keyStorePassword.toCharArray());
+        sc = SSLContext.getInstance("TLS");
+        sc.init(kmf.getKeyManagers(), trustManager, new SecureRandom());
+    }
+
+    @Override
+    public SSLContext get() {
+        return sc;
+    }
+}
\ No newline at end of file
diff --git a/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/location/SystemAndNetworkSegmentToLocationSupplier.java b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/location/SystemAndNetworkSegmentToLocationSupplier.java
new file mode 100644
index 0000000..569d3ae
--- /dev/null
+++ b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/location/SystemAndNetworkSegmentToLocationSupplier.java
@@ -0,0 +1,120 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.fujitsu.fgcp.location;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.ExecutionException;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+import org.jclouds.domain.Location;
+import org.jclouds.domain.LocationBuilder;
+import org.jclouds.domain.LocationScope;
+import org.jclouds.fujitsu.fgcp.FGCPAsyncApi;
+import org.jclouds.fujitsu.fgcp.domain.VNet;
+import org.jclouds.fujitsu.fgcp.domain.VSystem;
+import org.jclouds.fujitsu.fgcp.domain.VSystemWithDetails;
+import org.jclouds.location.suppliers.LocationsSupplier;
+import org.jclouds.location.suppliers.all.RegionToProviderOrJustProvider;
+
+import com.google.common.base.Throwables;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.ImmutableSet.Builder;
+import com.google.common.collect.Iterables;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+
+/**
+ * Builds location hierarchy by querying the back-end for the networks of all
+ * virtual systems.
+ * <p>
+ * Example:
+ * <p>
+ * 
+ * <pre>
+ * >location provider fgcp(-au)
+ * -> location region au/nsw
+ * --> location system vsys
+ * ---> location network DMZ/SECURE1/SECURE2
+ * </pre>
+ * 
+ * Todo: caching - provider/region won't change. if vsys still exists, network
+ * won't change
+ * 
+ * @author Dies Koper
+ */
+@Singleton
+public class SystemAndNetworkSegmentToLocationSupplier implements
+        LocationsSupplier {
+
+    private final RegionToProviderOrJustProvider regionProvider;
+    private FGCPAsyncApi api;
+
+    @Inject
+    SystemAndNetworkSegmentToLocationSupplier(
+            RegionToProviderOrJustProvider regionProvider, FGCPAsyncApi api) {
+        this.regionProvider = checkNotNull(regionProvider,
+                "regionToProviderOrJustProvider");
+        this.api = checkNotNull(api, "api");
+    }
+
+    @Override
+    public Set<Location> get() {
+        Builder<Location> locations = ImmutableSet.builder();
+        try {
+            List<ListenableFuture<VSystemWithDetails>> futures = new ArrayList<ListenableFuture<VSystemWithDetails>>();
+            for (VSystem system : api.getVirtualDCApi().listVirtualSystems()
+                    .get()) {
+
+                futures.add(api.getVirtualSystemApi()
+                        .getDetails(system.getId()));
+            }
+            for (VSystemWithDetails system : Futures.successfulAsList(futures)
+                    .get()) {
+
+                Location systemLocation = new LocationBuilder()
+                        .scope(LocationScope.SYSTEM)
+                        .parent(Iterables.getOnlyElement(regionProvider.get()))
+                        .description(system.getName()).id(system.getId())
+                        .build();
+
+                for (VNet net : system.getNetworks()) {
+
+                    locations.add(new LocationBuilder()
+                            .scope(LocationScope.NETWORK)
+                            .parent(systemLocation)
+                            .description(
+                                    net.getNetworkId().replaceFirst(
+                                            ".+(DMZ|SECURE.)", "\\1"))
+                            .id(net.getNetworkId()).build());
+                }
+            }
+        } catch (InterruptedException e) {
+            throw Throwables.propagate(e);
+        } catch (ExecutionException e) {
+            throw Throwables.propagate(e);
+        }
+        return locations.build();
+    }
+}
\ No newline at end of file
diff --git a/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/reference/RequestParameters.java b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/reference/RequestParameters.java
new file mode 100644
index 0000000..d4870c5
--- /dev/null
+++ b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/reference/RequestParameters.java
@@ -0,0 +1,81 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.fujitsu.fgcp.reference;
+
+/**
+ * Configuration parameters and constants used in HTTP requests.
+ * 
+ * @author Dies Koper
+ */
+public interface RequestParameters {
+
+    /**
+     * Indicates the action to perform. Example: ListVSYS
+     */
+    public static final String ACTION = "Action";
+
+    /**
+     * The API version to use. Example: 2011-01-31
+     */
+    public static final String VERSION = "Version";
+
+    /**
+     * The locale to use. Example: en
+     */
+    public static final String LOCALE = "Locale";
+
+    /**
+     * The Access Key ID for the request sender. This identifies the account
+     * which will be charged for usage of the service. The account with which
+     * the Access Key ID is associated must be signed up for FGCP, or requests
+     * will not be accepted. AKIADQKE4SARGYLE
+     */
+    public static final String ACCESS_KEY_ID = "AccessKeyId";
+
+    /**
+     * The date and time at which the request is signed, in the format
+     * YYYY-MM-DDThh:mm:ssZ. For more information, go to ISO 8601. Example:
+     * 2006-07-07T15:04:56Z
+     */
+    public static final String TIMESTAMP = "Timestamp";
+
+    /**
+     * The date and time at which the signer included in the request expires, in
+     * the format YYYY-MM-DDThh:mm:ssZ. Example: 2006-07-07T15:04:56Z
+     */
+    public static final String EXPIRES = "Expires";
+
+    /**
+     * The request signer. For more information, go to the Amazon Elastic
+     * Compute Cloud Developer Guide. Example: Qnpl4Qk/7tINHzfXCiT7VbBatDA=
+     */
+    public static final String SIGNATURE = "Signature";
+
+    /**
+     * The hash algorithm you use to create the request signer. Valid value:
+     * SHA1withRSA.
+     */
+    public static final String SIGNATURE_METHOD = "SignatureMethod";
+
+    /**
+     * The signer version you use to sign the request. Set this value to 1.0.
+     * 
+     */
+    public static final String SIGNATURE_VERSION = "SignatureVersion";
+}
diff --git a/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/services/AdditionalDiskApi.java b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/services/AdditionalDiskApi.java
new file mode 100644
index 0000000..2b4cbb6
--- /dev/null
+++ b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/services/AdditionalDiskApi.java
@@ -0,0 +1,53 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.fujitsu.fgcp.services;
+
+import java.util.Set;
+import java.util.concurrent.TimeUnit;
+
+import org.jclouds.concurrent.Timeout;
+import org.jclouds.fujitsu.fgcp.domain.VDisk;
+import org.jclouds.fujitsu.fgcp.domain.VDiskStatus;
+
+/**
+ * API relating to additional storage.
+ * 
+ * @author Dies Koper
+ */
+@Timeout(duration = 60, timeUnit = TimeUnit.SECONDS)
+public interface AdditionalDiskApi {
+
+    VDiskStatus getStatus(String id);
+
+    VDisk get(String id);
+
+    void update(String id, String name, String value);
+
+    void backup(String id);
+
+    void restore(String systemId, String backupId);
+
+    void destroy(String id);
+
+    void detach(String diskId, String serverId);
+
+    void destroyBackup(String sysId, String backupId);
+
+    // Set<> listBackups(String sysId);
+}
diff --git a/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/services/AdditionalDiskAsyncApi.java b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/services/AdditionalDiskAsyncApi.java
new file mode 100644
index 0000000..440be5b
--- /dev/null
+++ b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/services/AdditionalDiskAsyncApi.java
@@ -0,0 +1,112 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.fujitsu.fgcp.services;
+
+import java.util.Set;
+import java.util.concurrent.TimeUnit;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.MediaType;
+
+import org.jclouds.concurrent.Timeout;
+import org.jclouds.fujitsu.fgcp.FGCPAsyncApi;
+import org.jclouds.fujitsu.fgcp.binders.BindAlsoToSystemId;
+import org.jclouds.fujitsu.fgcp.compute.functions.SingleElementResponseToElement;
+import org.jclouds.fujitsu.fgcp.domain.VDisk;
+import org.jclouds.fujitsu.fgcp.domain.VDiskStatus;
+import org.jclouds.fujitsu.fgcp.filters.RequestAuthenticator;
+import org.jclouds.fujitsu.fgcp.reference.RequestParameters;
+import org.jclouds.rest.annotations.BinderParam;
+import org.jclouds.rest.annotations.JAXBResponseParser;
+import org.jclouds.rest.annotations.PayloadParams;
+import org.jclouds.rest.annotations.QueryParams;
+import org.jclouds.rest.annotations.RequestFilters;
+import org.jclouds.rest.annotations.Transform;
+
+import com.google.common.util.concurrent.ListenableFuture;
+
+/**
+ * Non-blocking API relating to additional storage.
+ * 
+ * @author Dies Koper
+ */
+@RequestFilters(RequestAuthenticator.class)
+@QueryParams(keys = RequestParameters.VERSION, values = FGCPAsyncApi.VERSION)
+@PayloadParams(keys = RequestParameters.VERSION, values = FGCPAsyncApi.VERSION)
+@Consumes(MediaType.TEXT_XML)
+@Timeout(duration = 60, timeUnit = TimeUnit.SECONDS)
+public interface AdditionalDiskAsyncApi {
+
+    @GET
+    @JAXBResponseParser
+    @QueryParams(keys = "Action", values = "GetVDiskStatus")
+    @Transform(SingleElementResponseToElement.class)
+    ListenableFuture<VDiskStatus> getStatus(
+            @BinderParam(BindAlsoToSystemId.class) @QueryParam("vdiskId") String id);
+
+    @GET
+    @JAXBResponseParser
+    @QueryParams(keys = "Action", values = "GetVDiskAttributes")
+    @Transform(SingleElementResponseToElement.class)
+    ListenableFuture<VDisk> get(
+            @BinderParam(BindAlsoToSystemId.class) @QueryParam("vdiskId") String id);
+
+    @GET
+    @QueryParams(keys = "Action", values = "UpdateVDiskAttribute")
+    ListenableFuture<Void> update(
+            @BinderParam(BindAlsoToSystemId.class) @QueryParam("vdiskId") String id,
+            @QueryParam("attributeName") String name,
+            @QueryParam("attributeValue") String value);
+
+    @GET
+    @JAXBResponseParser
+    @QueryParams(keys = "Action", values = "BackupVDisk")
+    ListenableFuture<Void> backup(
+            @BinderParam(BindAlsoToSystemId.class) @QueryParam("vdiskId") String id);
+
+    @GET
+    @JAXBResponseParser
+    @QueryParams(keys = "Action", values = "RestoreVDisk")
+    ListenableFuture<Void> restore(@QueryParam("vsysId") String systemId,
+            @QueryParam("backupId") String backupId);
+
+    @GET
+    @JAXBResponseParser
+    @QueryParams(keys = "Action", values = "DestroyVDisk")
+    ListenableFuture<Void> destroy(
+            @BinderParam(BindAlsoToSystemId.class) @QueryParam("vdiskId") String id);
+
+    @GET
+    @JAXBResponseParser
+    @QueryParams(keys = "Action", values = "DetachVDisk")
+    ListenableFuture<Void> detach(
+            @BinderParam(BindAlsoToSystemId.class) @QueryParam("vdiskId") String diskId,
+            @QueryParam("vserverId") String serverId);
+
+    @GET
+    @JAXBResponseParser
+    @QueryParams(keys = "Action", values = "DestroyVDiskBackup")
+    ListenableFuture<Void> destroyBackup(@QueryParam("vsysId") String sysId,
+            @QueryParam("backupId") String backupId);
+
+    // Set<> listBackups(String sysId);
+
+}
diff --git a/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/services/BuiltinServerApi.java b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/services/BuiltinServerApi.java
new file mode 100644
index 0000000..274b1fb
--- /dev/null
+++ b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/services/BuiltinServerApi.java
@@ -0,0 +1,73 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.fujitsu.fgcp.services;
+
+import java.util.Set;
+import java.util.concurrent.TimeUnit;
+
+import org.jclouds.concurrent.Timeout;
+import org.jclouds.fujitsu.fgcp.domain.BuiltinServer;
+import org.jclouds.fujitsu.fgcp.domain.BuiltinServerBackup;
+import org.jclouds.fujitsu.fgcp.domain.BuiltinServerConfiguration;
+import org.jclouds.fujitsu.fgcp.domain.BuiltinServerStatus;
+
+/**
+ * API relating to built-in servers, also called extended function module (EFM),
+ * such as a firewall or load balancer (SLB).
+ * 
+ * @author Dies Koper
+ */
+@Timeout(duration = 60, timeUnit = TimeUnit.SECONDS)
+public interface BuiltinServerApi {
+
+    void start(String id);
+
+    void stop(String id);
+
+    void destroy(String id);
+
+    void backup(String id);
+
+    void restore(String id, String backupId);
+
+    Set<BuiltinServerBackup> listBackups(String id);
+
+    void destroyBackup(String id, String backupId);
+
+    BuiltinServer get(String id);
+
+    void update(String id, String name, String value);
+
+    BuiltinServerStatus getStatus(String id);
+
+    BuiltinServer getConfiguration(String id, BuiltinServerConfiguration configuration);
+
+    //    BuiltinServer getConfiguration(String id, BuiltinServerConfiguration configuration, ConfigurationRequest request);
+    // void updateConfiguration(String id, xml?);
+    /*
+getDNSConfiguration(String id)
+getNATConfiguration(String id)
+getPolicyConfiguration(String id)
+getLBConfiguration(String id)
+
+     *    UpdateEFMConfiguration
+    BuiltinServer getConfiguration(String id, BuiltinServerConfiguration configuration);
+
+     */
+}
diff --git a/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/services/BuiltinServerAsyncApi.java b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/services/BuiltinServerAsyncApi.java
new file mode 100644
index 0000000..569577f
--- /dev/null
+++ b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/services/BuiltinServerAsyncApi.java
@@ -0,0 +1,145 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.fujitsu.fgcp.services;
+
+import java.util.Set;
+import java.util.concurrent.TimeUnit;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.MediaType;
+
+import org.jclouds.concurrent.Timeout;
+import org.jclouds.fujitsu.fgcp.FGCPAsyncApi;
+import org.jclouds.fujitsu.fgcp.binders.BindAlsoToSystemId;
+import org.jclouds.fujitsu.fgcp.compute.functions.SingleElementResponseToElement;
+import org.jclouds.fujitsu.fgcp.domain.BuiltinServer;
+import org.jclouds.fujitsu.fgcp.domain.BuiltinServerBackup;
+import org.jclouds.fujitsu.fgcp.domain.BuiltinServerConfiguration;
+import org.jclouds.fujitsu.fgcp.domain.BuiltinServerStatus;
+import org.jclouds.fujitsu.fgcp.filters.RequestAuthenticator;
+import org.jclouds.fujitsu.fgcp.reference.RequestParameters;
+import org.jclouds.rest.annotations.BinderParam;
+import org.jclouds.rest.annotations.JAXBResponseParser;
+import org.jclouds.rest.annotations.PayloadParams;
+import org.jclouds.rest.annotations.QueryParams;
+import org.jclouds.rest.annotations.RequestFilters;
+import org.jclouds.rest.annotations.Transform;
+
+import com.google.common.util.concurrent.ListenableFuture;
+
+/**
+ * Non-blocking API relating to built-in servers, also called extended function
+ * module (EFM), such as a firewall or load balancer (SLB).
+ * 
+ * @author Dies Koper
+ */
+@RequestFilters(RequestAuthenticator.class)
+@QueryParams(keys = RequestParameters.VERSION, values = FGCPAsyncApi.VERSION)
+@PayloadParams(keys = RequestParameters.VERSION, values = FGCPAsyncApi.VERSION)
+@Consumes(MediaType.TEXT_XML)
+@Timeout(duration = 60, timeUnit = TimeUnit.SECONDS)
+public interface BuiltinServerAsyncApi {
+
+    @GET
+    @JAXBResponseParser
+    @QueryParams(keys = "Action", values = "StartEFM")
+    ListenableFuture<Void> start(
+            @BinderParam(BindAlsoToSystemId.class) @QueryParam("efmId") String id);
+
+    @GET
+    @JAXBResponseParser
+    @QueryParams(keys = "Action", values = "StopEFM")
+    ListenableFuture<Void> stop(
+            @BinderParam(BindAlsoToSystemId.class) @QueryParam("efmId") String id);
+
+    @GET
+    @JAXBResponseParser
+    @QueryParams(keys = "Action", values = "DestroyEFM")
+    ListenableFuture<Void> destroy(
+            @BinderParam(BindAlsoToSystemId.class) @QueryParam("efmId") String id);
+
+    @GET
+    @JAXBResponseParser
+    @QueryParams(keys = "Action", values = "BackupEFM")
+    ListenableFuture<Void> backup(
+            @BinderParam(BindAlsoToSystemId.class) @QueryParam("efmId") String id);
+
+    @GET
+    @JAXBResponseParser
+    @QueryParams(keys = "Action", values = "RestoreEFM")
+    ListenableFuture<Void> restore(
+            @BinderParam(BindAlsoToSystemId.class) @QueryParam("efmId") String id,
+            @QueryParam("backupId") String backupId);
+
+    @GET
+    @JAXBResponseParser
+    @QueryParams(keys = "Action", values = "ListEFMBackup")
+    ListenableFuture<Set<BuiltinServerBackup>> listBackups(
+            @BinderParam(BindAlsoToSystemId.class) @QueryParam("efmId") String id);
+
+    @GET
+    @JAXBResponseParser
+    @QueryParams(keys = "Action", values = "DestroyEFMBackup")
+    ListenableFuture<Void> destroyBackup(
+            @BinderParam(BindAlsoToSystemId.class) @QueryParam("efmId") String id,
+            @QueryParam("backupId") String backupId);
+
+    @GET
+    @JAXBResponseParser
+    @QueryParams(keys = "Action", values = "GetEFMAttributes")
+    @Transform(SingleElementResponseToElement.class)
+    ListenableFuture<BuiltinServer> get(
+            @BinderParam(BindAlsoToSystemId.class) @QueryParam("efmId") String id);
+
+    @GET
+    @JAXBResponseParser
+    @QueryParams(keys = "Action", values = "UpdateEFMAttribute")
+    ListenableFuture<Void> update(
+            @BinderParam(BindAlsoToSystemId.class) @QueryParam("efmId") String id,
+            @QueryParam("attributeName") String name,
+            @QueryParam("attributeValue") String value);
+
+    @GET
+    @JAXBResponseParser
+    @QueryParams(keys = "Action", values = "GetEFMStatus")
+    @Transform(SingleElementResponseToElement.class)
+    ListenableFuture<BuiltinServerStatus> getStatus(
+            @BinderParam(BindAlsoToSystemId.class) @QueryParam("efmId") String id);
+
+    @GET
+    @JAXBResponseParser
+    @QueryParams(keys = "Action", values = "GetEFMConfiguration")
+    @Transform(SingleElementResponseToElement.class)
+    ListenableFuture<BuiltinServer> getConfiguration(
+            @BinderParam(BindAlsoToSystemId.class) @QueryParam("efmId") String id,
+            @QueryParam("configurationName") BuiltinServerConfiguration configuration);
+
+//  @POST
+//  @JAXBResponseParser
+//  @QueryParams(keys = "Action", values = "GetEFMConfiguration")
+//  @Transform(SingleElementResponseToElement.class)
+//  ListenableFuture<Set<Rule>> getUpdateDetails(String id);
+
+    // ListenableFuture<Void>
+    // updateConfiguration(@BinderParam(BindAlsoToSystemId.class)
+    // @QueryParam("efmId") String id, xml?);
+//    EFM_UPDATE,         getUpdateStatus(String id);
+}
diff --git a/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/services/DiskImageApi.java b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/services/DiskImageApi.java
new file mode 100644
index 0000000..610e61d
--- /dev/null
+++ b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/services/DiskImageApi.java
@@ -0,0 +1,39 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.fujitsu.fgcp.services;
+
+import java.util.concurrent.TimeUnit;
+
+import org.jclouds.concurrent.Timeout;
+import org.jclouds.fujitsu.fgcp.domain.DiskImage;
+
+/**
+ * API relating to disk images.
+ * 
+ * @author Dies Koper
+ */
+@Timeout(duration = 60, timeUnit = TimeUnit.SECONDS)
+public interface DiskImageApi {
+
+    DiskImage get(String id);
+
+    void update(String diskImageId, String localeId, String name, String value);
+
+    void deregister(String id);
+}
diff --git a/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/services/DiskImageAsyncApi.java b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/services/DiskImageAsyncApi.java
new file mode 100644
index 0000000..9b4d613
--- /dev/null
+++ b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/services/DiskImageAsyncApi.java
@@ -0,0 +1,73 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.fujitsu.fgcp.services;
+
+import java.util.concurrent.TimeUnit;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.MediaType;
+
+import org.jclouds.concurrent.Timeout;
+import org.jclouds.fujitsu.fgcp.FGCPAsyncApi;
+import org.jclouds.fujitsu.fgcp.compute.functions.SingleElementResponseToElement;
+import org.jclouds.fujitsu.fgcp.domain.DiskImage;
+import org.jclouds.fujitsu.fgcp.filters.RequestAuthenticator;
+import org.jclouds.fujitsu.fgcp.reference.RequestParameters;
+import org.jclouds.rest.annotations.JAXBResponseParser;
+import org.jclouds.rest.annotations.PayloadParams;
+import org.jclouds.rest.annotations.QueryParams;
+import org.jclouds.rest.annotations.RequestFilters;
+import org.jclouds.rest.annotations.Transform;
+
+import com.google.common.util.concurrent.ListenableFuture;
+
+/**
+ * Non-blocking API relating to disk images.
+ * 
+ * @author Dies Koper
+ */
+@RequestFilters(RequestAuthenticator.class)
+@QueryParams(keys = RequestParameters.VERSION, values = FGCPAsyncApi.VERSION)
+@PayloadParams(keys = RequestParameters.VERSION, values = FGCPAsyncApi.VERSION)
+@Consumes(MediaType.TEXT_XML)
+@Timeout(duration = 60, timeUnit = TimeUnit.SECONDS)
+public interface DiskImageAsyncApi {
+
+    @GET
+    @JAXBResponseParser
+    @QueryParams(keys = "Action", values = "GetDiskImageAttributes")
+    @Transform(SingleElementResponseToElement.class)
+    ListenableFuture<DiskImage> get(@QueryParam("diskImageId") String id);
+
+    @GET
+    @JAXBResponseParser
+    @QueryParams(keys = "Action", values = "UpdateDiskImageAttribute")
+    ListenableFuture<Void> update(
+            @QueryParam("diskImageId") String diskImageId,
+            @QueryParam("updateLcId") String localeId,
+            @QueryParam("attributeName") String name,
+            @QueryParam("attributeValue") String value);
+
+    @GET
+    @JAXBResponseParser
+    @QueryParams(keys = "Action", values = "UnregisterDiskImage")
+    ListenableFuture<Void> deregister(@QueryParam("diskImageId") String id);
+}
diff --git a/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/services/FirewallApi.java b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/services/FirewallApi.java
new file mode 100644
index 0000000..bfe54e9
--- /dev/null
+++ b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/services/FirewallApi.java
@@ -0,0 +1,37 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.fujitsu.fgcp.services;
+
+import java.util.Set;
+import java.util.concurrent.TimeUnit;
+
+import org.jclouds.concurrent.Timeout;
+import org.jclouds.fujitsu.fgcp.domain.Rule;
+
+/**
+ * API relating to a system's built-in server of type firewall.
+ * 
+ * @author Dies Koper
+ */
+@Timeout(duration = 60, timeUnit = TimeUnit.SECONDS)
+public interface FirewallApi extends BuiltinServerApi {
+
+    Set<Rule> getNATConfiguration(String id);
+    
+}
diff --git a/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/services/FirewallAsyncApi.java b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/services/FirewallAsyncApi.java
new file mode 100644
index 0000000..df06dc9
--- /dev/null
+++ b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/services/FirewallAsyncApi.java
@@ -0,0 +1,79 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.fujitsu.fgcp.services;
+
+import java.util.Set;
+import java.util.concurrent.TimeUnit;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.MediaType;
+
+import org.jclouds.concurrent.Timeout;
+import org.jclouds.fujitsu.fgcp.FGCPAsyncApi;
+import org.jclouds.fujitsu.fgcp.binders.BindAlsoToSystemId;
+import org.jclouds.fujitsu.fgcp.compute.functions.SingleElementResponseToElement;
+import org.jclouds.fujitsu.fgcp.domain.BuiltinServer;
+import org.jclouds.fujitsu.fgcp.domain.BuiltinServerBackup;
+import org.jclouds.fujitsu.fgcp.domain.BuiltinServerConfiguration;
+import org.jclouds.fujitsu.fgcp.domain.BuiltinServerStatus;
+import org.jclouds.fujitsu.fgcp.domain.Rule;
+import org.jclouds.fujitsu.fgcp.filters.RequestAuthenticator;
+import org.jclouds.fujitsu.fgcp.reference.RequestParameters;
+import org.jclouds.rest.annotations.BinderParam;
+import org.jclouds.rest.annotations.JAXBResponseParser;
+import org.jclouds.rest.annotations.PayloadParams;
+import org.jclouds.rest.annotations.QueryParams;
+import org.jclouds.rest.annotations.RequestFilters;
+import org.jclouds.rest.annotations.Transform;
+
+import com.google.common.util.concurrent.ListenableFuture;
+
+/**
+ * Non-blocking API relating to a built-in server, also called extended function
+ * module (EFM), of type firewall.
+ * 
+ * @author Dies Koper
+ */
+@RequestFilters(RequestAuthenticator.class)
+@QueryParams(keys = RequestParameters.VERSION, values = FGCPAsyncApi.VERSION)
+@PayloadParams(keys = RequestParameters.VERSION, values = FGCPAsyncApi.VERSION)
+@Consumes(MediaType.TEXT_XML)
+@Timeout(duration = 60, timeUnit = TimeUnit.SECONDS)
+public interface FirewallAsyncApi extends BuiltinServerAsyncApi {
+
+    @POST
+    @JAXBResponseParser
+    @QueryParams(keys = "Action", values = "GetEFMConfiguration")
+    @Transform(SingleElementResponseToElement.class)
+    ListenableFuture<Set<Rule>> getNATConfiguration(String id);
+
+    /*
+    FW_NAT_RULE,        getNATConfiguration(String id)
+
+    FW_DNS,         getDNSConfiguration(String id)
+    FW_POLICY,          getPolicyConfiguration(String id)
+
+    FW_LOG,         getFirewallLogs(String id);
+    FW_LIMIT_POLICY,
+
+     */
+}
diff --git a/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/services/LoadBalancerApi.java b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/services/LoadBalancerApi.java
new file mode 100644
index 0000000..d1c6309
--- /dev/null
+++ b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/services/LoadBalancerApi.java
@@ -0,0 +1,33 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.fujitsu.fgcp.services;
+
+import java.util.concurrent.TimeUnit;
+
+import org.jclouds.concurrent.Timeout;
+
+/**
+ * API relating to a built-in server of type software load balancer (SLB).
+ * 
+ * @author Dies Koper
+ */
+@Timeout(duration = 60, timeUnit = TimeUnit.SECONDS)
+public interface LoadBalancerApi extends BuiltinServerApi {
+
+}
diff --git a/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/services/LoadBalancerAsyncApi.java b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/services/LoadBalancerAsyncApi.java
new file mode 100644
index 0000000..a7a6452
--- /dev/null
+++ b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/services/LoadBalancerAsyncApi.java
@@ -0,0 +1,69 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.fujitsu.fgcp.services;
+
+import java.util.Set;
+import java.util.concurrent.TimeUnit;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.MediaType;
+
+import org.jclouds.concurrent.Timeout;
+import org.jclouds.fujitsu.fgcp.FGCPAsyncApi;
+import org.jclouds.fujitsu.fgcp.binders.BindAlsoToSystemId;
+import org.jclouds.fujitsu.fgcp.compute.functions.SingleElementResponseToElement;
+import org.jclouds.fujitsu.fgcp.domain.BuiltinServer;
+import org.jclouds.fujitsu.fgcp.domain.BuiltinServerBackup;
+import org.jclouds.fujitsu.fgcp.domain.BuiltinServerConfiguration;
+import org.jclouds.fujitsu.fgcp.domain.BuiltinServerStatus;
+import org.jclouds.fujitsu.fgcp.filters.RequestAuthenticator;
+import org.jclouds.fujitsu.fgcp.reference.RequestParameters;
+import org.jclouds.rest.annotations.BinderParam;
+import org.jclouds.rest.annotations.JAXBResponseParser;
+import org.jclouds.rest.annotations.PayloadParams;
+import org.jclouds.rest.annotations.QueryParams;
+import org.jclouds.rest.annotations.RequestFilters;
+import org.jclouds.rest.annotations.Transform;
+
+import com.google.common.util.concurrent.ListenableFuture;
+
+/**
+ * Non-blocking API relating to a built-in server, also called extended function
+ * module (EFM), of type load balancer (SLB).
+ * 
+ * @author Dies Koper
+ */
+@RequestFilters(RequestAuthenticator.class)
+@QueryParams(keys = RequestParameters.VERSION, values = FGCPAsyncApi.VERSION)
+@PayloadParams(keys = RequestParameters.VERSION, values = FGCPAsyncApi.VERSION)
+@Consumes(MediaType.TEXT_XML)
+@Timeout(duration = 60, timeUnit = TimeUnit.SECONDS)
+public interface LoadBalancerAsyncApi extends BuiltinServerAsyncApi {
+
+    /*
+    SLB_RULE,           getLBConfiguration(String id)
+    SLB_LOAD_STATISTICS,    getLoadBalancerStats(String id)
+    SLB_ERROR_STATISTICS,   getLoadBalancerErrorStats(String id)
+    SLB_CERTIFICATE_LIST,   getLoadBalancerCerts(String id)
+    SLB_CONNECTION,     getLoadBalancerConnection(String id)
+
+     */
+}
diff --git a/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/services/PublicIPAddressApi.java b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/services/PublicIPAddressApi.java
new file mode 100644
index 0000000..9bb4035
--- /dev/null
+++ b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/services/PublicIPAddressApi.java
@@ -0,0 +1,44 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.fujitsu.fgcp.services;
+
+import java.util.concurrent.TimeUnit;
+
+import org.jclouds.concurrent.Timeout;
+import org.jclouds.fujitsu.fgcp.domain.PublicIP;
+import org.jclouds.fujitsu.fgcp.domain.PublicIPStatus;
+
+/**
+ * API relating to public IP addresses.
+ * 
+ * @author Dies Koper
+ */
+@Timeout(duration = 60, timeUnit = TimeUnit.SECONDS)
+public interface PublicIPAddressApi {
+
+    void attach(String systemId, String ip);
+
+    void detach(String systemId, String ip);
+
+    void free(String systemId, String ip);
+
+    PublicIPStatus getStatus(String ip);
+
+    PublicIP get(String ip);
+}
diff --git a/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/services/PublicIPAddressAsyncApi.java b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/services/PublicIPAddressAsyncApi.java
new file mode 100644
index 0000000..0b50dc7
--- /dev/null
+++ b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/services/PublicIPAddressAsyncApi.java
@@ -0,0 +1,87 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.fujitsu.fgcp.services;
+
+import java.util.Set;
+import java.util.concurrent.TimeUnit;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.MediaType;
+
+import org.jclouds.concurrent.Timeout;
+import org.jclouds.fujitsu.fgcp.FGCPAsyncApi;
+import org.jclouds.fujitsu.fgcp.compute.functions.SingleElementResponseToElement;
+import org.jclouds.fujitsu.fgcp.domain.PublicIP;
+import org.jclouds.fujitsu.fgcp.domain.PublicIPStatus;
+import org.jclouds.fujitsu.fgcp.filters.RequestAuthenticator;
+import org.jclouds.fujitsu.fgcp.reference.RequestParameters;
+import org.jclouds.rest.annotations.JAXBResponseParser;
+import org.jclouds.rest.annotations.PayloadParams;
+import org.jclouds.rest.annotations.QueryParams;
+import org.jclouds.rest.annotations.RequestFilters;
+import org.jclouds.rest.annotations.Transform;
+
+import com.google.common.util.concurrent.ListenableFuture;
+
+/**
+ * Non-blocking API relating to public IP addresses.
+ * 
+ * @author Dies Koper
+ */
+@RequestFilters(RequestAuthenticator.class)
+@QueryParams(keys = RequestParameters.VERSION, values = FGCPAsyncApi.VERSION)
+@PayloadParams(keys = RequestParameters.VERSION, values = FGCPAsyncApi.VERSION)
+@Consumes(MediaType.TEXT_XML)
+@Timeout(duration = 60, timeUnit = TimeUnit.SECONDS)
+public interface PublicIPAddressAsyncApi {
+
+    @GET
+    @JAXBResponseParser
+    @QueryParams(keys = "Action", values = "AttachPublicIP")
+    ListenableFuture<Void> attach(@QueryParam("vsysId") String systemId,
+            @QueryParam("publicIp") String ip);
+
+    @GET
+    @JAXBResponseParser
+    @QueryParams(keys = "Action", values = "DetachPublicIP")
+    ListenableFuture<Void> detach(@QueryParam("vsysId") String systemId,
+            @QueryParam("publicIp") String ip);
+
+    @GET
+    @JAXBResponseParser
+    @QueryParams(keys = "Action", values = "GetPublicIPStatus")
+    @Transform(SingleElementResponseToElement.class)
+    ListenableFuture<PublicIPStatus> getStatus(
+            @QueryParam("publicIp") String ip);
+
+    @GET
+    @JAXBResponseParser
+    @QueryParams(keys = "Action", values = "GetPublicIPAttributes")
+    @Transform(SingleElementResponseToElement.class)
+    ListenableFuture<PublicIP> get(@QueryParam("publicIp") String ip);
+
+    @GET
+    @JAXBResponseParser
+    @QueryParams(keys = "Action", values = "FreePublicIP")
+    ListenableFuture<Void> free(@QueryParam("vsysId") String systemId,
+            @QueryParam("publicIp") String ip);
+
+}
diff --git a/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/services/SystemTemplateApi.java b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/services/SystemTemplateApi.java
new file mode 100644
index 0000000..e995a72
--- /dev/null
+++ b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/services/SystemTemplateApi.java
@@ -0,0 +1,43 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.fujitsu.fgcp.services;
+
+import java.util.concurrent.TimeUnit;
+
+import org.jclouds.concurrent.Timeout;
+import org.jclouds.fujitsu.fgcp.domain.VSystemDescriptor;
+
+/**
+ * API relating to system templates, also referred to as virtual system
+ * descriptors.
+ * 
+ * @author Dies Koper
+ */
+@Timeout(duration = 60, timeUnit = TimeUnit.SECONDS)
+public interface SystemTemplateApi {
+
+    VSystemDescriptor get(String id);
+
+    void update(String id, String localeId, String name, String value);
+
+    void deregister(String id);
+
+    void deregisterPrivateTemplate(String id);
+
+}
diff --git a/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/services/SystemTemplateAsyncApi.java b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/services/SystemTemplateAsyncApi.java
new file mode 100644
index 0000000..74a93b2
--- /dev/null
+++ b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/services/SystemTemplateAsyncApi.java
@@ -0,0 +1,81 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.fujitsu.fgcp.services;
+
+import java.util.concurrent.TimeUnit;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.MediaType;
+
+import org.jclouds.concurrent.Timeout;
+import org.jclouds.fujitsu.fgcp.FGCPAsyncApi;
+import org.jclouds.fujitsu.fgcp.compute.functions.SingleElementResponseToElement;
+import org.jclouds.fujitsu.fgcp.domain.VSystemDescriptor;
+import org.jclouds.fujitsu.fgcp.filters.RequestAuthenticator;
+import org.jclouds.fujitsu.fgcp.reference.RequestParameters;
+import org.jclouds.rest.annotations.JAXBResponseParser;
+import org.jclouds.rest.annotations.PayloadParams;
+import org.jclouds.rest.annotations.QueryParams;
+import org.jclouds.rest.annotations.RequestFilters;
+import org.jclouds.rest.annotations.Transform;
+
+import com.google.common.util.concurrent.ListenableFuture;
+
+/**
+ * Non-blocking API relating to system templates, also referred to as virtual
+ * system descriptors.
+ * 
+ * @author Dies Koper
+ */
+@RequestFilters(RequestAuthenticator.class)
+@QueryParams(keys = RequestParameters.VERSION, values = FGCPAsyncApi.VERSION)
+@PayloadParams(keys = RequestParameters.VERSION, values = FGCPAsyncApi.VERSION)
+@Consumes(MediaType.TEXT_XML)
+@Timeout(duration = 60, timeUnit = TimeUnit.SECONDS)
+public interface SystemTemplateAsyncApi {
+
+    @GET
+    @JAXBResponseParser
+    @QueryParams(keys = "Action", values = "GetVSYSDescriptorConfiguration")
+    @Transform(SingleElementResponseToElement.class)
+    ListenableFuture<VSystemDescriptor> get(
+            @QueryParam("vsysDescriptorId") String id);
+
+    @GET
+    @JAXBResponseParser
+    @QueryParams(keys = "Action", values = "UpdateVSYSDescriptorAttribute")
+    ListenableFuture<Void> update(@QueryParam("vsysDescriptorId") String id,
+            @QueryParam("updateLcId") String localeId,
+            @QueryParam("attributeName") String name,
+            @QueryParam("attributeValue") String value);
+
+    @GET
+    @JAXBResponseParser
+    @QueryParams(keys = "Action", values = "UnregisterVSYSDescriptor")
+    ListenableFuture<Void> deregister(
+            @QueryParam("vsysDescriptorId") String id);
+
+    @GET
+    @JAXBResponseParser
+    @QueryParams(keys = "Action", values = "UnregisterPrivateVSYSDescriptor")
+    ListenableFuture<Void> deregisterPrivateTemplate(
+            @QueryParam("vsysDescriptorId") String id);
+}
diff --git a/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/services/VirtualDCApi.java b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/services/VirtualDCApi.java
new file mode 100644
index 0000000..bb3ec35
--- /dev/null
+++ b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/services/VirtualDCApi.java
@@ -0,0 +1,75 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.fujitsu.fgcp.services;
+
+import org.jclouds.concurrent.Timeout;
+import org.jclouds.fujitsu.fgcp.domain.*;
+
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * API relating to the virtual data center.
+ * 
+ * @author Dies Koper
+ */
+@Timeout(duration = 60, timeUnit = TimeUnit.SECONDS)
+public interface VirtualDCApi {
+
+    String createVirtualSystem(String descriptorId, String name);
+
+    Set<VSystem> listVirtualSystems();
+
+    // according to the manual it takes a 'String diskImageId' but value seems
+    // to be ignored
+    Set<ServerType> listServerTypes();
+
+    Set<DiskImage> listDiskImages();
+
+    Set<DiskImage> listDiskImages(String serverCategory,
+            String vsysDescriptorId);
+
+    Map<PublicIP, String> listPublicIPs();
+
+    void addAddressRange(String pipFrom, String pipTo);
+
+    void createAddressPool(String pipFrom, String pipTo);
+
+    void deleteAddressRange(String pipFrom, String pipTo);
+
+    Set<AddressRange> getAddressRange();
+
+    Set<VSystemDescriptor> listVSYSDescriptor();
+
+    Set<VSystemDescriptor> listVSYSDescriptor(String keyword, int estimateFrom,
+            int estimateTo);
+
+    Set<EventLog> getEventLogs(boolean all);
+
+    Set<EventLog> getEventLogs();
+
+    Set<Information> getInformation(boolean all);
+
+    Set<Information> getInformation();
+
+    Set<UsageInfo> getSystemUsage();
+
+    Set<UsageInfo> getSystemUsage(String systemIds);
+}
diff --git a/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/services/VirtualDCAsyncApi.java b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/services/VirtualDCAsyncApi.java
new file mode 100644
index 0000000..ec4bad9
--- /dev/null
+++ b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/services/VirtualDCAsyncApi.java
@@ -0,0 +1,189 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.fujitsu.fgcp.services;
+
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.TimeUnit;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.MediaType;
+
+import org.jclouds.concurrent.Timeout;
+import org.jclouds.fujitsu.fgcp.FGCPAsyncApi;
+import org.jclouds.fujitsu.fgcp.compute.functions.SingleElementResponseToElement;
+import org.jclouds.fujitsu.fgcp.domain.AddressRange;
+import org.jclouds.fujitsu.fgcp.domain.DiskImage;
+import org.jclouds.fujitsu.fgcp.domain.EventLog;
+import org.jclouds.fujitsu.fgcp.domain.Information;
+import org.jclouds.fujitsu.fgcp.domain.PublicIP;
+import org.jclouds.fujitsu.fgcp.domain.ServerType;
+import org.jclouds.fujitsu.fgcp.domain.UsageInfo;
+import org.jclouds.fujitsu.fgcp.domain.VSystem;
+import org.jclouds.fujitsu.fgcp.domain.VSystemDescriptor;
+import org.jclouds.fujitsu.fgcp.filters.RequestAuthenticator;
+import org.jclouds.fujitsu.fgcp.reference.RequestParameters;
+import org.jclouds.rest.annotations.JAXBResponseParser;
+import org.jclouds.rest.annotations.PayloadParams;
+import org.jclouds.rest.annotations.QueryParams;
+import org.jclouds.rest.annotations.RequestFilters;
+import org.jclouds.rest.annotations.Transform;
+
+import com.google.common.util.concurrent.ListenableFuture;
+
+/**
+ * Non-blocking API relating to the virtual data center.
+ * 
+ * @author Dies Koper
+ */
+@RequestFilters(RequestAuthenticator.class)
+@QueryParams(keys = RequestParameters.VERSION, values = FGCPAsyncApi.VERSION)
+@PayloadParams(keys = RequestParameters.VERSION, values = FGCPAsyncApi.VERSION)
+@Consumes(MediaType.TEXT_XML)
+@Timeout(duration = 60, timeUnit = TimeUnit.SECONDS)
+public interface VirtualDCAsyncApi {
+
+    // @POST
+    @GET
+    @JAXBResponseParser
+    // @XMLResponseParser(VSYSCreateHandler.class)
+    @QueryParams(keys = "Action", values = "CreateVSYS")
+    @Transform(SingleElementResponseToElement.class)
+    // @PayloadParams(keys = "Action", values = "CreateVSYS")
+    // @Produces(MediaType.TEXT_XML)
+    // @MapBinder(BindParamsToXmlPayload.class)
+    // ListenableFuture<String>
+    // createVirtualSystem(@PayloadParam("vsysDescriptorId") String
+    // vsysDescriptorId, @PayloadParam("vsysName") String vsysName);
+    ListenableFuture<String> createVirtualSystem(
+            @QueryParam("vsysDescriptorId") String descriptorId,
+            @QueryParam("vsysName") String name);
+
+    @GET
+    @JAXBResponseParser
+    // @XMLResponseParser(VSYSListHandler.class)
+    @QueryParams(keys = "Action", values = "ListVSYS")
+    ListenableFuture<Set<VSystem>> listVirtualSystems();
+
+    @GET
+    @JAXBResponseParser
+    // according to the manual it takes a 'String diskImageId' but value seems
+    // to be ignored
+    @QueryParams(keys = { "Action", "diskImageId" }, values = {
+            "ListServerType", "dummy" })
+    // @XmlJavaTypeAdapter(SetOfServerTypesXMLAdapter.class)
+    // @XmlElement(type = ServerType.class)
+    ListenableFuture<Set<ServerType>> listServerTypes();
+
+    @GET
+    @JAXBResponseParser
+    @QueryParams(keys = "Action", values = "ListDiskImage")
+    ListenableFuture<Set<DiskImage>> listDiskImages();
+
+    @GET
+    @JAXBResponseParser
+    @QueryParams(keys = "Action", values = "ListDiskImage")
+    ListenableFuture<Set<DiskImage>> listDiskImages(
+            @QueryParam("serverCategory") String serverCategory,
+            @QueryParam("vsysDescriptorId") String vsysDescriptorId);
+
+    /**
+     *
+     * @return
+     * @see VirtualSystemAsyncApi#listPublicIPs(String)
+     */
+    @GET
+    @JAXBResponseParser
+    @QueryParams(keys = "Action", values = "ListPublicIP")
+    ListenableFuture<Map<PublicIP, String>> listPublicIPs();
+
+    @GET
+    @JAXBResponseParser
+    @QueryParams(keys = "Action", values = "AddAddressRange")
+    ListenableFuture<Void> addAddressRange(
+            @QueryParam("pipFrom") String pipFrom,
+            @QueryParam("pipTo") String pipTo);
+
+    @GET
+    @JAXBResponseParser
+    @QueryParams(keys = "Action", values = "CreateAddressPool")
+    ListenableFuture<Void> createAddressPool(
+            @QueryParam("pipFrom") String pipFrom,
+            @QueryParam("pipTo") String pipTo);
+
+    @GET
+    @JAXBResponseParser
+    @QueryParams(keys = "Action", values = "DeleteAddressRange")
+    ListenableFuture<Void> deleteAddressRange(
+            @QueryParam("pipFrom") String pipFrom,
+            @QueryParam("pipTo") String pipTo);
+
+    @GET
+    @JAXBResponseParser
+    @QueryParams(keys = "Action", values = "GetAddressRange")
+    ListenableFuture<Set<AddressRange>> getAddressRange();
+
+    @GET
+    @JAXBResponseParser
+    @QueryParams(keys = "Action", values = "ListVSYSDescriptor")
+    ListenableFuture<Set<VSystemDescriptor>> listVSYSDescriptor();
+
+    @GET
+    @JAXBResponseParser
+    @QueryParams(keys = "Action", values = "ListVSYSDescriptor")
+    ListenableFuture<Set<VSystemDescriptor>> listVSYSDescriptor(
+            @QueryParam("keyword") String keyword,
+            @QueryParam("estimateFrom") int estimateFrom,
+            @QueryParam("estimateTo") int estimateTo);
+
+    @GET
+    @JAXBResponseParser
+    @QueryParams(keys = "Action", values = "GetEventLog")
+    ListenableFuture<Set<EventLog>> getEventLogs();
+
+    @GET
+    @JAXBResponseParser
+    @QueryParams(keys = "Action", values = "GetEventLog")
+    ListenableFuture<Set<EventLog>> getEventLogs(@QueryParam("all") boolean all);
+
+    @GET
+    @JAXBResponseParser
+    @QueryParams(keys = "Action", values = "GetInformation")
+    ListenableFuture<Set<Information>> getInformation();
+
+    @GET
+    @JAXBResponseParser
+    @QueryParams(keys = "Action", values = "GetInformation")
+    ListenableFuture<Set<Information>> getInformation(
+            @QueryParam("all") boolean all);
+
+    @GET
+    @JAXBResponseParser
+    @QueryParams(keys = "Action", values = "GetSystemUsage")
+    ListenableFuture<Set<UsageInfo>> getSystemUsage();
+
+    @GET
+    @JAXBResponseParser
+    @QueryParams(keys = "Action", values = "GetSystemUsage")
+    ListenableFuture<Set<UsageInfo>> getSystemUsage(
+            @QueryParam("systemIds") String systemIds);
+
+}
diff --git a/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/services/VirtualServerApi.java b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/services/VirtualServerApi.java
new file mode 100644
index 0000000..70be613
--- /dev/null
+++ b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/services/VirtualServerApi.java
@@ -0,0 +1,61 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.fujitsu.fgcp.services;
+
+import java.util.Set;
+import java.util.concurrent.TimeUnit;
+
+import org.jclouds.concurrent.Timeout;
+import org.jclouds.fujitsu.fgcp.domain.PerformanceInfo;
+import org.jclouds.fujitsu.fgcp.domain.VServer;
+import org.jclouds.fujitsu.fgcp.domain.VServerStatus;
+import org.jclouds.fujitsu.fgcp.domain.VServerWithDetails;
+
+/**
+ * API relating to virtual servers.
+ * 
+ * @author Dies Koper
+ */
+@Timeout(duration = 60, timeUnit = TimeUnit.SECONDS)
+public interface VirtualServerApi {
+
+    void start(String id);
+
+    void stop(String id);
+
+    void stopForcefully(String id);
+
+    void destroy(String id);
+
+    VServer get(String id);
+
+    VServerWithDetails getDetails(String id);
+
+    void update(String id, String name, String value);
+
+    VServerStatus getStatus(String id);
+
+    String getInitialPassword(String id);
+
+    void attachDisk(String serverId, String diskId);
+
+    Set<PerformanceInfo> getPerformanceInformation(String id, String interval);
+
+    void registerAsPrivateDiskImage(String xml);
+}
diff --git a/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/services/VirtualServerAsyncApi.java b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/services/VirtualServerAsyncApi.java
new file mode 100644
index 0000000..5159c3b
--- /dev/null
+++ b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/services/VirtualServerAsyncApi.java
@@ -0,0 +1,148 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.fujitsu.fgcp.services;
+
+import java.util.Set;
+import java.util.concurrent.TimeUnit;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.MediaType;
+
+import org.jclouds.concurrent.Timeout;
+import org.jclouds.fujitsu.fgcp.FGCPAsyncApi;
+import org.jclouds.fujitsu.fgcp.binders.BindAlsoToSystemId;
+import org.jclouds.fujitsu.fgcp.compute.functions.SingleElementResponseToElement;
+import org.jclouds.fujitsu.fgcp.domain.PerformanceInfo;
+import org.jclouds.fujitsu.fgcp.domain.VServer;
+import org.jclouds.fujitsu.fgcp.domain.VServerStatus;
+import org.jclouds.fujitsu.fgcp.domain.VServerWithDetails;
+import org.jclouds.fujitsu.fgcp.filters.RequestAuthenticator;
+import org.jclouds.fujitsu.fgcp.reference.RequestParameters;
+import org.jclouds.rest.annotations.BinderParam;
+import org.jclouds.rest.annotations.JAXBResponseParser;
+import org.jclouds.rest.annotations.PayloadParams;
+import org.jclouds.rest.annotations.QueryParams;
+import org.jclouds.rest.annotations.RequestFilters;
+import org.jclouds.rest.annotations.Transform;
+
+import com.google.common.util.concurrent.ListenableFuture;
+
+/**
+ * Non-blocking API relating to virtual servers.
+ * 
+ * @author Dies Koper
+ */
+@RequestFilters(RequestAuthenticator.class)
+@QueryParams(keys = RequestParameters.VERSION, values = FGCPAsyncApi.VERSION)
+@PayloadParams(keys = RequestParameters.VERSION, values = FGCPAsyncApi.VERSION)
+@Consumes(MediaType.TEXT_XML)
+@Timeout(duration = 60, timeUnit = TimeUnit.SECONDS)
+public interface VirtualServerAsyncApi {
+
+    @GET
+    @JAXBResponseParser
+    @QueryParams(keys = "Action", values = "StartVServer")
+    ListenableFuture<Void> start(
+            @BinderParam(BindAlsoToSystemId.class) @QueryParam("vserverId") String id);
+
+    @GET
+    @JAXBResponseParser
+    @QueryParams(keys = "Action", values = "StopVServer")
+    ListenableFuture<Void> stop(
+            @BinderParam(BindAlsoToSystemId.class) @QueryParam("vserverId") String id);
+
+    @GET
+    @JAXBResponseParser
+    @QueryParams(keys = { "Action", "force" }, values = { "StopVServer", "true" })
+    ListenableFuture<Void> stopForcefully(
+            @BinderParam(BindAlsoToSystemId.class) @QueryParam("vserverId") String id);
+
+    @GET
+    @JAXBResponseParser
+    @QueryParams(keys = "Action", values = "DestroyVServer")
+    ListenableFuture<Void> destroy(
+            @BinderParam(BindAlsoToSystemId.class) @QueryParam("vserverId") String id);
+
+    @GET
+    @JAXBResponseParser
+    @QueryParams(keys = "Action", values = "GetVServerAttributes")
+    @Transform(SingleElementResponseToElement.class)
+    ListenableFuture<VServer> get(
+            @BinderParam(BindAlsoToSystemId.class) @QueryParam("vserverId") String id);
+
+    @GET
+    @JAXBResponseParser
+    @QueryParams(keys = "Action", values = "GetVServerConfiguration")
+    @Transform(SingleElementResponseToElement.class)
+    ListenableFuture<VServerWithDetails> getDetails(
+            @BinderParam(BindAlsoToSystemId.class) @QueryParam("vserverId") String id);
+
+    @GET
+    @JAXBResponseParser
+    @QueryParams(keys = "Action", values = "UpdateVServerAttribute")
+    ListenableFuture<Void> update(
+            @BinderParam(BindAlsoToSystemId.class) @QueryParam("vserverId") String id,
+            @QueryParam("attributeName") String name,
+            @QueryParam("attributeValue") String value);
+
+    @GET
+    @JAXBResponseParser
+    @QueryParams(keys = "Action", values = "GetVServerStatus")
+    // @Transform(StringToVServerStatus.class)
+    @Transform(SingleElementResponseToElement.class)
+    ListenableFuture<VServerStatus> getStatus(
+            @BinderParam(BindAlsoToSystemId.class) @QueryParam("vserverId") String id);
+
+    @GET
+    @JAXBResponseParser
+    @QueryParams(keys = "Action", values = "GetVServerInitialPassword")
+    @Transform(SingleElementResponseToElement.class)
+    ListenableFuture<String> getInitialPassword(
+            @BinderParam(BindAlsoToSystemId.class) @QueryParam("vserverId") String id);
+
+    @GET
+    @JAXBResponseParser
+    @QueryParams(keys = "Action", values = "AttachVDisk")
+    ListenableFuture<Void> attachDisk(
+            @BinderParam(BindAlsoToSystemId.class) @QueryParam("vserverId") String serverId,
+            @QueryParam("vdiskId") String diskId);
+
+    @GET
+    @JAXBResponseParser
+    @QueryParams(keys = "Action", values = "GetPerformanceInformation")
+    ListenableFuture<Set<PerformanceInfo>> getPerformanceInformation(
+            @BinderParam(BindAlsoToSystemId.class) @QueryParam("serverId") String id,
+            @QueryParam("interval") String interval);
+
+    @GET
+    @JAXBResponseParser
+    @QueryParams(keys = "Action", values = "GetPerformanceInformation")
+    ListenableFuture<Set<PerformanceInfo>> getPerformanceInformation(
+            @BinderParam(BindAlsoToSystemId.class) @QueryParam("serverId") String id,
+            @QueryParam("dataType") String dataType,
+            @QueryParam("interval") String interval);
+
+    @POST
+    @JAXBResponseParser
+    @QueryParams(keys = "Action", values = "RegisterPrivateDiskImage")
+    ListenableFuture<Void> registerAsPrivateDiskImage(String xml);
+}
diff --git a/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/services/VirtualSystemApi.java b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/services/VirtualSystemApi.java
new file mode 100644
index 0000000..5ec7020
--- /dev/null
+++ b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/services/VirtualSystemApi.java
@@ -0,0 +1,74 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.fujitsu.fgcp.services;
+
+import java.util.Set;
+import java.util.concurrent.TimeUnit;
+
+import org.jclouds.concurrent.Timeout;
+import org.jclouds.fujitsu.fgcp.domain.BuiltinServer;
+import org.jclouds.fujitsu.fgcp.domain.PublicIP;
+import org.jclouds.fujitsu.fgcp.domain.VDisk;
+import org.jclouds.fujitsu.fgcp.domain.VServer;
+import org.jclouds.fujitsu.fgcp.domain.VSystem;
+import org.jclouds.fujitsu.fgcp.domain.VSystemStatus;
+import org.jclouds.fujitsu.fgcp.domain.VSystemWithDetails;
+
+/**
+ * API relating to virtual systems.
+ * 
+ * @author Dies Koper
+ */
+@Timeout(duration = 60, timeUnit = TimeUnit.SECONDS)
+public interface VirtualSystemApi {
+
+    void destroy(String id);
+
+    VSystemStatus getStatus(String id);
+
+    VSystem get(String id);
+
+    VSystemWithDetails getDetails(String id);
+
+    void update(String id, String name, String value);
+
+    void updateConfiguration(String id, String name, String value);
+
+    String createServer(String name, String type, String diskImageId,
+            String networkId);
+
+    Set<VServer> listServers(String id);
+
+    String createBuiltinServer(String name, String networkId);
+
+    Set<BuiltinServer> listBuiltinServers(String id, String type);
+
+    String createDisk(String id, String name, int size);
+
+    Set<VDisk> listDisks(String id);
+
+    void allocatePublicIP(String id);
+
+    Set<PublicIP> listPublicIPs(String id);
+
+    String standByConsole(String id, String networkId);
+
+    void registerAsPrivateVSYSDescriptor(String id,
+            String vsysDescriptorXMLFilePath);
+}
diff --git a/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/services/VirtualSystemAsyncApi.java b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/services/VirtualSystemAsyncApi.java
new file mode 100644
index 0000000..c9d4d20
--- /dev/null
+++ b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/services/VirtualSystemAsyncApi.java
@@ -0,0 +1,174 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.fujitsu.fgcp.services;
+
+import java.util.Set;
+import java.util.concurrent.TimeUnit;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.MediaType;
+
+import org.jclouds.concurrent.Timeout;
+import org.jclouds.fujitsu.fgcp.FGCPAsyncApi;
+import org.jclouds.fujitsu.fgcp.binders.BindAlsoToSystemId;
+import org.jclouds.fujitsu.fgcp.compute.functions.SingleElementResponseToElement;
+import org.jclouds.fujitsu.fgcp.domain.BuiltinServer;
+import org.jclouds.fujitsu.fgcp.domain.PublicIP;
+import org.jclouds.fujitsu.fgcp.domain.VDisk;
+import org.jclouds.fujitsu.fgcp.domain.VServer;
+import org.jclouds.fujitsu.fgcp.domain.VSystem;
+import org.jclouds.fujitsu.fgcp.domain.VSystemStatus;
+import org.jclouds.fujitsu.fgcp.domain.VSystemWithDetails;
+import org.jclouds.fujitsu.fgcp.filters.RequestAuthenticator;
+import org.jclouds.fujitsu.fgcp.reference.RequestParameters;
+import org.jclouds.rest.annotations.BinderParam;
+import org.jclouds.rest.annotations.JAXBResponseParser;
+import org.jclouds.rest.annotations.PayloadParams;
+import org.jclouds.rest.annotations.QueryParams;
+import org.jclouds.rest.annotations.RequestFilters;
+import org.jclouds.rest.annotations.Transform;
+
+import com.google.common.util.concurrent.ListenableFuture;
+
+/**
+ * Non-blocking API relating to virtual systems.
+ * 
+ * @author Dies Koper
+ */
+@RequestFilters(RequestAuthenticator.class)
+@QueryParams(keys = RequestParameters.VERSION, values = FGCPAsyncApi.VERSION)
+@PayloadParams(keys = RequestParameters.VERSION, values = FGCPAsyncApi.VERSION)
+@Consumes(MediaType.TEXT_XML)
+@Timeout(duration = 60, timeUnit = TimeUnit.SECONDS)
+public interface VirtualSystemAsyncApi {
+
+    @GET
+    @JAXBResponseParser
+    @QueryParams(keys = "Action", values = "DestroyVSYS")
+    ListenableFuture<Void> destroy(@QueryParam("vsysId") String id);
+
+    @GET
+    @JAXBResponseParser
+    @QueryParams(keys = "Action", values = "GetVSYSStatus")
+    @Transform(SingleElementResponseToElement.class)
+    ListenableFuture<VSystemStatus> getStatus(@QueryParam("vsysId") String id);
+
+    @GET
+    @JAXBResponseParser
+    @QueryParams(keys = "Action", values = "GetVSYSAttributes")
+    @Transform(SingleElementResponseToElement.class)
+    ListenableFuture<VSystem> get(@QueryParam("vsysId") String id);
+
+    @GET
+    @JAXBResponseParser
+    @QueryParams(keys = "Action", values = "GetVSYSConfiguration")
+    @Transform(SingleElementResponseToElement.class)
+    ListenableFuture<VSystemWithDetails> getDetails(
+            @QueryParam("vsysId") String id);
+
+    @GET
+    @JAXBResponseParser
+    @QueryParams(keys = "Action", values = "UpdateVSYSAttribute")
+    ListenableFuture<Void> update(@QueryParam("vsysId") String id,
+            @QueryParam("attributeName") String name,
+            @QueryParam("attributeValue") String value);
+
+    @GET
+    @JAXBResponseParser
+    @QueryParams(keys = "Action", values = "UpdateVSYSConfiguration")
+    ListenableFuture<Void> updateConfiguration(@QueryParam("vsysId") String id,
+            @QueryParam("configurationName") String name,
+            @QueryParam("configurationValue") String value);
+
+    @GET
+    @JAXBResponseParser
+    @QueryParams(keys = "Action", values = "CreateVServer")
+    @Transform(SingleElementResponseToElement.class)
+    ListenableFuture<String> createServer(
+            @QueryParam("vserverName") String name,
+            @QueryParam("vserverType") String type,
+            @QueryParam("diskImageId") String diskImageId,
+            @BinderParam(BindAlsoToSystemId.class) @QueryParam("networkId") String networkId);
+
+    @GET
+    @JAXBResponseParser
+    @QueryParams(keys = "Action", values = "ListVServer")
+    ListenableFuture<Set<VServer>> listServers(@QueryParam("vsysId") String id);
+
+    @GET
+    @JAXBResponseParser
+    @QueryParams(keys = "Action", values = "CreateVDisk")
+    @Transform(SingleElementResponseToElement.class)
+    ListenableFuture<String> createDisk(@QueryParam("vsysId") String id,
+            @QueryParam("vdiskName") String name, @QueryParam("size") int size);
+
+    @GET
+    @JAXBResponseParser
+    @QueryParams(keys = "Action", values = "ListVDisk")
+    ListenableFuture<Set<VDisk>> listDisks(@QueryParam("vsysId") String id);
+
+    @GET
+    @JAXBResponseParser
+    @QueryParams(keys = "Action", values = "AllocatePublicIP")
+    ListenableFuture<Void> allocatePublicIP(@QueryParam("vsysId") String id);
+
+    /**
+     *
+     * @return
+     * @see VirtualDCAsyncApi#listPublicIPs()
+     */
+    @GET
+    @JAXBResponseParser
+    @QueryParams(keys = "Action", values = "ListPublicIP")
+    @Transform(SingleElementResponseToElement.class)
+    ListenableFuture<Set<PublicIP>> listPublicIPs(
+            @QueryParam("vsysId") String id);
+
+    @GET
+    @JAXBResponseParser
+    // SLB is the only built-in server that can currently be created so
+    // hard-code it
+    @QueryParams(keys = { "Action", "efmType" }, values = { "CreateEFM", "SLB" })
+    @Transform(SingleElementResponseToElement.class)
+    ListenableFuture<String> createBuiltinServer(
+            @QueryParam("efmName") String name,
+            @BinderParam(BindAlsoToSystemId.class) @QueryParam("networkId") String networkId);
+
+    @GET
+    @JAXBResponseParser
+    @QueryParams(keys = "Action", values = "ListEFM")
+    ListenableFuture<Set<BuiltinServer>> listBuiltinServers(
+            @QueryParam("vsysId") String id, @QueryParam("efmType") String type);
+
+    @GET
+    @JAXBResponseParser
+    @QueryParams(keys = "Action", values = "StandByConsole")
+    @Transform(SingleElementResponseToElement.class)
+    ListenableFuture<String> standByConsole(@QueryParam("vsysId") String id,
+            @QueryParam("networkId") String networkId);
+
+    @GET
+    @JAXBResponseParser
+    @QueryParams(keys = "Action", values = "RegisterPrivateVSYSDescriptor")
+    ListenableFuture<Void> registerAsPrivateVSYSDescriptor(
+            @QueryParam("vsysId") String id,
+            @QueryParam("vsysDescriptorXMLFilePath") String vsysDescriptorXMLFilePath);
+}
diff --git a/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/xml/BindParamsToXmlPayload.java b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/xml/BindParamsToXmlPayload.java
new file mode 100644
index 0000000..0783787
--- /dev/null
+++ b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/xml/BindParamsToXmlPayload.java
@@ -0,0 +1,96 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.fujitsu.fgcp.xml;
+
+import com.google.common.base.Strings;
+import org.jclouds.fujitsu.fgcp.reference.RequestParameters;
+import org.jclouds.http.HttpRequest;
+import org.jclouds.rest.MapBinder;
+import org.jclouds.rest.binders.BindToStringPayload;
+
+import javax.ws.rs.core.MediaType;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.Map;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * Not currently used but leaving for reference when implementing multipart POST
+ * methods.
+ * 
+ * @author Dies Koper
+ */
+public class BindParamsToXmlPayload extends BindToStringPayload implements
+        MapBinder {
+
+    @Override
+    public <R extends HttpRequest> R bindToRequest(R request,
+            Map<String, Object> mapParams) {
+        String action = checkNotNull(
+                mapParams.remove(RequestParameters.ACTION),
+                RequestParameters.ACTION).toString();
+        String version = Strings.nullToEmpty((String) mapParams
+                .remove(RequestParameters.VERSION));
+
+        StringBuilder xml = new StringBuilder();
+        xml.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n");
+        xml.append("<OViSSRequest>\r\n");
+        xml.append("  <Action>" + action + "</Action>\r\n");
+
+        for (Map.Entry<String, Object> entry : mapParams.entrySet()) {
+            String key = entry.getKey();
+            xml.append("  <" + key + ">" + checkNotNull(mapParams.get(key))
+                    + "</" + key + ">\r\n");
+        }
+
+        xml.append("  <Version>" + version + "</Version>\r\n");
+        xml.append("  <Locale></Locale>\r\n"); // value inserted in
+                                               // RequestAuthenticator#filter
+        xml.append("  <AccessKeyId></AccessKeyId>\r\n"); // value inserted in
+                                                         // RequestAuthenticator#filter
+        xml.append("  <Signature></Signature>\r\n"); // value inserted in
+                                                     // RequestAuthenticator#filter
+        xml.append("</OViSSRequest>");
+
+        request = super.bindToRequest(request, xml);
+        request.getPayload().getContentMetadata()
+                .setContentType(MediaType.TEXT_XML);
+
+        // remove version query param if set as it was moved to the xml body
+        URI uri = request.getEndpoint();
+        URI uriWithoutQueryParams;
+        try {
+            uriWithoutQueryParams = new URI(uri.getScheme(), uri.getUserInfo(),
+                    uri.getHost(), uri.getPort(), uri.getPath(), null,
+                    uri.getFragment());
+        } catch (URISyntaxException e) {
+            // should never happen as we're copying the components from a URI
+            uriWithoutQueryParams = uri;
+        }
+
+        return (R) request.toBuilder().endpoint(uriWithoutQueryParams).build();
+    }
+
+    @Override
+    public <R extends HttpRequest> R bindToRequest(R request, Object toBind) {
+        throw new IllegalArgumentException(
+                "BindParamsToXmlPayload needs bind parameters");
+    }
+}
diff --git a/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/xml/FGCPJAXBParser.java b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/xml/FGCPJAXBParser.java
new file mode 100644
index 0000000..b5349ab
--- /dev/null
+++ b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/xml/FGCPJAXBParser.java
@@ -0,0 +1,88 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.fujitsu.fgcp.xml;
+
+import java.io.IOException;
+import java.io.StringReader;
+
+import javax.inject.Singleton;
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBException;
+import javax.xml.bind.Unmarshaller;
+
+import org.jclouds.fujitsu.fgcp.domain.VServerWithDetails;
+import org.jclouds.fujitsu.fgcp.xml.internal.ListServerTypeResponse;
+import org.jclouds.fujitsu.fgcp.xml.internal.StatusQuerable;
+import org.jclouds.http.HttpException;
+import org.jclouds.xml.XMLParser;
+
+/**
+ * Parses XML documents using JAXB.
+ * 
+ * @author Dies Koper
+ * @see org.jclouds.http.functions.ParseXMLWithJAXB
+ */
+@Singleton
+public class FGCPJAXBParser implements XMLParser {
+    JAXBContext context;
+
+    public FGCPJAXBParser() throws JAXBException {
+        context = JAXBContext.newInstance(VServerWithDetails.class.getPackage()
+                .getName()
+                + ":"
+                + ListServerTypeResponse.class.getPackage().getName(),
+                VServerWithDetails.class.getClassLoader());
+    }
+
+    @Override
+    public String toXML(final Object src) throws IOException {
+        return toXML(src, src.getClass());
+    }
+
+    @Override
+    public <T> String toXML(final Object src, final Class<T> type)
+            throws IOException {
+        throw new UnsupportedOperationException(
+                "only marshaling from XML is implemented");
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public <T> T fromXML(final String xml, final Class<T> type)
+            throws IOException {
+        T response = null;
+        try {
+            StringReader reader = new StringReader(xml);
+
+            Unmarshaller unmarshaller = context.createUnmarshaller();
+
+            response = (T) unmarshaller.unmarshal(reader);
+        } catch (Exception ex) {
+            throw new IOException("Could not unmarshal document", ex);
+        }
+
+        if (((StatusQuerable) response).isError()) {
+            throw new HttpException(
+                    ((StatusQuerable) response).getResponseMessage());
+        }
+
+        return response;
+    }
+
+}
diff --git a/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/xml/internal/CreateEFMResponse.java b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/xml/internal/CreateEFMResponse.java
new file mode 100644
index 0000000..237fde5
--- /dev/null
+++ b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/xml/internal/CreateEFMResponse.java
@@ -0,0 +1,44 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.fujitsu.fgcp.xml.internal;
+
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+
+/**
+ * Wrapper for CreateEFMResponse.
+ * 
+ * @author Dies Koper
+ */
+@XmlRootElement(name = "CreateEFMResponse")
+public class CreateEFMResponse extends StatusResponse implements
+        SingleElementResponse {
+    @XmlElement(required = true)
+    private String efmId;
+
+    @Override
+    public String toString() {
+        return getElement();
+    }
+
+    @Override
+    public String getElement() {
+        return efmId;
+    }
+}
diff --git a/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/xml/internal/CreateVDiskResponse.java b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/xml/internal/CreateVDiskResponse.java
new file mode 100644
index 0000000..b31a637
--- /dev/null
+++ b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/xml/internal/CreateVDiskResponse.java
@@ -0,0 +1,44 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.fujitsu.fgcp.xml.internal;
+
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+
+/**
+ * Wrapper for CreateVDiskResponse.
+ * 
+ * @author Dies Koper
+ */
+@XmlRootElement(name = "CreateVDiskResponse")
+public class CreateVDiskResponse extends StatusResponse implements
+        SingleElementResponse {
+    @XmlElement(required = true)
+    private String vdiskId;
+
+    @Override
+    public String toString() {
+        return getElement();
+    }
+
+    @Override
+    public String getElement() {
+        return vdiskId;
+    }
+}
diff --git a/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/xml/internal/CreateVSYSResponse.java b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/xml/internal/CreateVSYSResponse.java
new file mode 100644
index 0000000..a18a3fa
--- /dev/null
+++ b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/xml/internal/CreateVSYSResponse.java
@@ -0,0 +1,44 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.fujitsu.fgcp.xml.internal;
+
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+
+/**
+ * Wrapper for CreateVSYSResponse.
+ * 
+ * @author Dies Koper
+ */
+@XmlRootElement(name = "CreateVSYSResponse")
+public class CreateVSYSResponse extends StatusResponse implements
+        SingleElementResponse {
+    @XmlElement(required = true)
+    private String vsysId;
+
+    @Override
+    public String toString() {
+        return getElement();
+    }
+
+    @Override
+    public String getElement() {
+        return vsysId;
+    }
+}
diff --git a/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/xml/internal/CreateVServerResponse.java b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/xml/internal/CreateVServerResponse.java
new file mode 100644
index 0000000..6170ee4
--- /dev/null
+++ b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/xml/internal/CreateVServerResponse.java
@@ -0,0 +1,44 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.fujitsu.fgcp.xml.internal;
+
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+
+/**
+ * Wrapper for CreateVServerResponse.
+ * 
+ * @author Dies Koper
+ */
+@XmlRootElement(name = "CreateVServerResponse")
+public class CreateVServerResponse extends StatusResponse implements
+        SingleElementResponse {
+    @XmlElement(required = true)
+    private String vserverId;
+
+    @Override
+    public String toString() {
+        return getElement();
+    }
+
+    @Override
+    public String getElement() {
+        return vserverId;
+    }
+}
diff --git a/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/xml/internal/GetAddressRangeResponse.java b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/xml/internal/GetAddressRangeResponse.java
new file mode 100644
index 0000000..9ea5571
--- /dev/null
+++ b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/xml/internal/GetAddressRangeResponse.java
@@ -0,0 +1,50 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.fujitsu.fgcp.xml.internal;
+
+import java.util.Collections;
+import java.util.LinkedHashSet;
+import java.util.Set;
+
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlElementWrapper;
+import javax.xml.bind.annotation.XmlRootElement;
+
+import org.jclouds.fujitsu.fgcp.domain.AddressRange;
+
+import com.google.common.collect.ImmutableSet;
+
+/**
+ * Wrapper for GetAddressRangeResponse.
+ * 
+ * @author Dies Koper
+ */
+@XmlRootElement(name = "GetAddressRangeResponse")
+public class GetAddressRangeResponse extends
+        SetWithStatusResponse<AddressRange> {
+    @XmlElementWrapper(name = "addressranges")
+    @XmlElement(name = "addressrange")
+    private Set<AddressRange> ranges = new LinkedHashSet<AddressRange>();
+
+    @Override
+    protected Set<AddressRange> delegate() {
+        return ranges == null ? ImmutableSet.<AddressRange> of() : Collections
+                .unmodifiableSet(ranges);
+    }
+}
diff --git a/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/xml/internal/GetDiskImageAttributesResponse.java b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/xml/internal/GetDiskImageAttributesResponse.java
new file mode 100644
index 0000000..ccef26f
--- /dev/null
+++ b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/xml/internal/GetDiskImageAttributesResponse.java
@@ -0,0 +1,46 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.fujitsu.fgcp.xml.internal;
+
+import org.jclouds.fujitsu.fgcp.domain.DiskImage;
+
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+
+/**
+ * Wrapper for GetDiskImageAttributesResponse.
+ * 
+ * @author Dies Koper
+ */
+@XmlRootElement(name = "GetDiskImageAttributesResponse")
+public class GetDiskImageAttributesResponse extends StatusResponse implements
+        SingleElementResponse {
+    @XmlElement(name = "diskimage")
+    private DiskImage diskImage;
+
+    @Override
+    public String toString() {
+        return getElement().toString();
+    }
+
+    @Override
+    public DiskImage getElement() {
+        return diskImage;
+    }
+}
\ No newline at end of file
diff --git a/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/xml/internal/GetEFMAttributesResponse.java b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/xml/internal/GetEFMAttributesResponse.java
new file mode 100644
index 0000000..9764a9e
--- /dev/null
+++ b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/xml/internal/GetEFMAttributesResponse.java
@@ -0,0 +1,46 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.fujitsu.fgcp.xml.internal;
+
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+
+import org.jclouds.fujitsu.fgcp.domain.BuiltinServer;
+
+/**
+ * Wrapper for GetEFMAttributesResponse.
+ * 
+ * @author Dies Koper
+ */
+@XmlRootElement(name = "GetEFMAttributesResponse")
+public class GetEFMAttributesResponse extends StatusResponse implements
+        SingleElementResponse {
+    @XmlElement(required = true)
+    private BuiltinServer efm;
+
+    @Override
+    public String toString() {
+        return getElement().toString();
+    }
+
+    @Override
+    public Object getElement() {
+        return efm;
+    }
+}
diff --git a/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/xml/internal/GetEFMStatusResponse.java b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/xml/internal/GetEFMStatusResponse.java
new file mode 100644
index 0000000..34fa4c6
--- /dev/null
+++ b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/xml/internal/GetEFMStatusResponse.java
@@ -0,0 +1,46 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.fujitsu.fgcp.xml.internal;
+
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+
+import org.jclouds.fujitsu.fgcp.domain.BuiltinServerStatus;
+
+/**
+ * Wrapper for GetEFMStatusResponse.
+ * 
+ * @author Dies Koper
+ */
+@XmlRootElement(name = "GetEFMStatusResponse")
+public class GetEFMStatusResponse extends StatusResponse implements
+        SingleElementResponse {
+    @XmlElement(required = true)
+    private BuiltinServerStatus efmStatus;
+
+    @Override
+    public String toString() {
+        return getElement().toString();
+    }
+
+    @Override
+    public Object getElement() {
+        return efmStatus;
+    }
+}
diff --git a/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/xml/internal/GetEventLogResponse.java b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/xml/internal/GetEventLogResponse.java
new file mode 100644
index 0000000..c9f35d2
--- /dev/null
+++ b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/xml/internal/GetEventLogResponse.java
@@ -0,0 +1,49 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.fujitsu.fgcp.xml.internal;
+
+import java.util.Collections;
+import java.util.LinkedHashSet;
+import java.util.Set;
+
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlElementWrapper;
+import javax.xml.bind.annotation.XmlRootElement;
+
+import org.jclouds.fujitsu.fgcp.domain.EventLog;
+
+import com.google.common.collect.ImmutableSet;
+
+/**
+ * Wrapper for GetEventLogResponse.
+ * 
+ * @author Dies Koper
+ */
+@XmlRootElement(name = "GetEventLogResponse")
+public class GetEventLogResponse extends SetWithStatusResponse<EventLog> {
+    @XmlElementWrapper(name = "eventlogs")
+    @XmlElement(name = "eventlog")
+    private Set<EventLog> logs = new LinkedHashSet<EventLog>();
+
+    @Override
+    protected Set<EventLog> delegate() {
+        return logs == null ? ImmutableSet.<EventLog> of() : Collections
+                .unmodifiableSet(logs);
+    }
+}
diff --git a/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/xml/internal/GetPerformanceInformationResponse.java b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/xml/internal/GetPerformanceInformationResponse.java
new file mode 100644
index 0000000..e8c9290
--- /dev/null
+++ b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/xml/internal/GetPerformanceInformationResponse.java
@@ -0,0 +1,50 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.fujitsu.fgcp.xml.internal;
+
+import java.util.Collections;
+import java.util.LinkedHashSet;
+import java.util.Set;
+
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlElementWrapper;
+import javax.xml.bind.annotation.XmlRootElement;
+
+import org.jclouds.fujitsu.fgcp.domain.PerformanceInfo;
+
+import com.google.common.collect.ImmutableSet;
+
+/**
+ * Wrapper for GetPerformanceInformationResponse.
+ * 
+ * @author Dies Koper
+ */
+@XmlRootElement(name = "GetPerformanceInformationResponse")
+public class GetPerformanceInformationResponse extends
+        SetWithStatusResponse<PerformanceInfo> {
+    @XmlElementWrapper(name = "performanceinfos")
+    @XmlElement(name = "performanceinfo")
+    private Set<PerformanceInfo> stats = new LinkedHashSet<PerformanceInfo>();
+
+    @Override
+    protected Set<PerformanceInfo> delegate() {
+        return stats == null ? ImmutableSet.<PerformanceInfo> of()
+                : Collections.unmodifiableSet(stats);
+    }
+}
diff --git a/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/xml/internal/GetPublicIPAttributesResponse.java b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/xml/internal/GetPublicIPAttributesResponse.java
new file mode 100644
index 0000000..d0a0488
--- /dev/null
+++ b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/xml/internal/GetPublicIPAttributesResponse.java
@@ -0,0 +1,53 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.fujitsu.fgcp.xml.internal;
+
+import java.util.Set;
+
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlElementWrapper;
+import javax.xml.bind.annotation.XmlRootElement;
+
+import org.jclouds.fujitsu.fgcp.domain.PublicIP;
+
+
+import com.google.common.collect.Iterables;
+
+/**
+ * Wrapper for GetPublicIPAttributesResponse.
+ * 
+ * @author Dies Koper
+ */
+@XmlRootElement(name = "GetPublicIPAttributesResponse")
+public class GetPublicIPAttributesResponse extends StatusResponse implements
+        SingleElementResponse {
+    @XmlElementWrapper(name = "publicips")
+    @XmlElement(name = "publicip")
+    private Set<PublicIP> publicIPs;
+
+    @Override
+    public String toString() {
+        return getElement().toString();
+    }
+
+    @Override
+    public Object getElement() {
+        return Iterables.getOnlyElement(publicIPs);
+    }
+}
diff --git a/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/xml/internal/GetPublicIPStatusResponse.java b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/xml/internal/GetPublicIPStatusResponse.java
new file mode 100644
index 0000000..29e5ce9
--- /dev/null
+++ b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/xml/internal/GetPublicIPStatusResponse.java
@@ -0,0 +1,46 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.fujitsu.fgcp.xml.internal;
+
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+
+import org.jclouds.fujitsu.fgcp.domain.PublicIPStatus;
+
+/**
+ * Wrapper for GetPublicIPStatusResponse.
+ * 
+ * @author Dies Koper
+ */
+@XmlRootElement(name = "GetPublicIPStatusResponse")
+public class GetPublicIPStatusResponse extends StatusResponse implements
+        SingleElementResponse {
+    @XmlElement(required = true)
+    private PublicIPStatus publicipStatus;
+
+    @Override
+    public String toString() {
+        return publicipStatus.toString();
+    }
+
+    @Override
+    public Object getElement() {
+        return publicipStatus;
+    }
+}
diff --git a/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/xml/internal/GetVDiskAttributesResponse.java b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/xml/internal/GetVDiskAttributesResponse.java
new file mode 100644
index 0000000..0634f00
--- /dev/null
+++ b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/xml/internal/GetVDiskAttributesResponse.java
@@ -0,0 +1,46 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.fujitsu.fgcp.xml.internal;
+
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+
+import org.jclouds.fujitsu.fgcp.domain.VDisk;
+
+/**
+ * Wrapper for GetVDiskAttributesResponse.
+ * 
+ * @author Dies Koper
+ */
+@XmlRootElement(name = "GetVDiskAttributesResponse")
+public class GetVDiskAttributesResponse extends StatusResponse implements
+        SingleElementResponse {
+    @XmlElement(required = true)
+    private VDisk vdisk;
+
+    @Override
+    public String toString() {
+        return getElement().toString();
+    }
+
+    @Override
+    public Object getElement() {
+        return vdisk;
+    }
+}
diff --git a/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/xml/internal/GetVSYSAttributesResponse.java b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/xml/internal/GetVSYSAttributesResponse.java
new file mode 100644
index 0000000..0833a4d
--- /dev/null
+++ b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/xml/internal/GetVSYSAttributesResponse.java
@@ -0,0 +1,46 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.fujitsu.fgcp.xml.internal;
+
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+
+import org.jclouds.fujitsu.fgcp.domain.VSystem;
+
+/**
+ * Wrapper for GetVSYSAttributesResponse.
+ * 
+ * @author Dies Koper
+ */
+@XmlRootElement(name = "GetVSYSAttributesResponse")
+public class GetVSYSAttributesResponse extends StatusResponse implements
+        SingleElementResponse {
+    @XmlElement(name = "vsys")
+    private VSystem system;
+
+    @Override
+    public String toString() {
+        return getElement().toString();
+    }
+
+    @Override
+    public Object getElement() {
+        return system;
+    }
+}
\ No newline at end of file
diff --git a/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/xml/internal/GetVSYSConfigurationResponse.java b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/xml/internal/GetVSYSConfigurationResponse.java
new file mode 100644
index 0000000..c593a3b
--- /dev/null
+++ b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/xml/internal/GetVSYSConfigurationResponse.java
@@ -0,0 +1,46 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.fujitsu.fgcp.xml.internal;
+
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+
+import org.jclouds.fujitsu.fgcp.domain.VSystemWithDetails;
+
+/**
+ * Wrapper for GetVSYSConfigurationResponse.
+ * 
+ * @author Dies Koper
+ */
+@XmlRootElement(name = "GetVSYSConfigurationResponse")
+public class GetVSYSConfigurationResponse extends StatusResponse implements
+        SingleElementResponse {
+    @XmlElement(name = "vsys")
+    private VSystemWithDetails system;
+
+    @Override
+    public String toString() {
+        return getElement().toString();
+    }
+
+    @Override
+    public Object getElement() {
+        return system;
+    }
+}
\ No newline at end of file
diff --git a/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/xml/internal/GetVSYSDescriptorConfigurationResponse.java b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/xml/internal/GetVSYSDescriptorConfigurationResponse.java
new file mode 100644
index 0000000..af21f20
--- /dev/null
+++ b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/xml/internal/GetVSYSDescriptorConfigurationResponse.java
@@ -0,0 +1,46 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.fujitsu.fgcp.xml.internal;
+
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+
+import org.jclouds.fujitsu.fgcp.domain.VSystemDescriptor;
+
+/**
+ * Wrapper for GetVSYSDescriptorConfigurationResponse.
+ * 
+ * @author Dies Koper
+ */
+@XmlRootElement(name = "GetVSYSDescriptorConfigurationResponse")
+public class GetVSYSDescriptorConfigurationResponse extends StatusResponse
+        implements SingleElementResponse {
+    @XmlElement
+    private VSystemDescriptor vsysdescriptor;
+
+    @Override
+    public String toString() {
+        return getElement().toString();
+    }
+
+    @Override
+    public Object getElement() {
+        return vsysdescriptor;
+    }
+}
\ No newline at end of file
diff --git a/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/xml/internal/GetVSYSStatusResponse.java b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/xml/internal/GetVSYSStatusResponse.java
new file mode 100644
index 0000000..08d1dc9
--- /dev/null
+++ b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/xml/internal/GetVSYSStatusResponse.java
@@ -0,0 +1,46 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.fujitsu.fgcp.xml.internal;
+
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+
+import org.jclouds.fujitsu.fgcp.domain.VSystemStatus;
+
+/**
+ * Wrapper for GetVSYSStatusResponse.
+ * 
+ * @author Dies Koper
+ */
+@XmlRootElement(name = "GetVSYSStatusResponse")
+public class GetVSYSStatusResponse extends StatusResponse implements
+        SingleElementResponse {
+    @XmlElement(required = true)
+    private VSystemStatus vsysStatus;
+
+    @Override
+    public String toString() {
+        return getElement().toString();
+    }
+
+    @Override
+    public Object getElement() {
+        return vsysStatus;
+    }
+}
diff --git a/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/xml/internal/GetVServerAttributesResponse.java b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/xml/internal/GetVServerAttributesResponse.java
new file mode 100644
index 0000000..404ccec
--- /dev/null
+++ b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/xml/internal/GetVServerAttributesResponse.java
@@ -0,0 +1,46 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.fujitsu.fgcp.xml.internal;
+
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+
+import org.jclouds.fujitsu.fgcp.domain.VServer;
+
+/**
+ * Wrapper for GetVServerAttributesResponse.
+ * 
+ * @author Dies Koper
+ */
+@XmlRootElement(name = "GetVServerAttributesResponse")
+public class GetVServerAttributesResponse extends StatusResponse implements
+        SingleElementResponse {
+    @XmlElement(required = true)
+    private VServer vserver;
+
+    @Override
+    public String toString() {
+        return vserver.toString();
+    }
+
+    @Override
+    public Object getElement() {
+        return vserver;
+    }
+}
diff --git a/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/xml/internal/GetVServerConfigurationResponse.java b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/xml/internal/GetVServerConfigurationResponse.java
new file mode 100644
index 0000000..f69daa5
--- /dev/null
+++ b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/xml/internal/GetVServerConfigurationResponse.java
@@ -0,0 +1,46 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.fujitsu.fgcp.xml.internal;
+
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+
+import org.jclouds.fujitsu.fgcp.domain.VServerWithDetails;
+
+/**
+ * Wrapper for GetVServerConfigurationResponse.
+ * 
+ * @author Dies Koper
+ */
+@XmlRootElement(name = "GetVServerConfigurationResponse")
+public class GetVServerConfigurationResponse extends StatusResponse implements
+        SingleElementResponse {
+    @XmlElement(required = true)
+    private VServerWithDetails vserver;
+
+    @Override
+    public String toString() {
+        return vserver.toString();
+    }
+
+    @Override
+    public Object getElement() {
+        return vserver;
+    }
+}
diff --git a/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/xml/internal/GetVServerInitialPasswordResponse.java b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/xml/internal/GetVServerInitialPasswordResponse.java
new file mode 100644
index 0000000..f5a1a16
--- /dev/null
+++ b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/xml/internal/GetVServerInitialPasswordResponse.java
@@ -0,0 +1,39 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.fujitsu.fgcp.xml.internal;
+
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+
+/**
+ * Wrapper for GetVServerInitialPasswordResponse.
+ * 
+ * @author Dies Koper
+ */
+@XmlRootElement(name = "GetVServerInitialPasswordResponse")
+public class GetVServerInitialPasswordResponse extends StatusResponse implements
+        SingleElementResponse {
+    @XmlElement(required = true)
+    private String initialPassword;
+
+    @Override
+    public Object getElement() {
+        return initialPassword;
+    }
+}
diff --git a/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/xml/internal/GetVServerStatusResponse.java b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/xml/internal/GetVServerStatusResponse.java
new file mode 100644
index 0000000..ea22965
--- /dev/null
+++ b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/xml/internal/GetVServerStatusResponse.java
@@ -0,0 +1,46 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.fujitsu.fgcp.xml.internal;
+
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+
+import org.jclouds.fujitsu.fgcp.domain.VServerStatus;
+
+/**
+ * Wrapper for GetVServerStatusResponse.
+ * 
+ * @author Dies Koper
+ */
+@XmlRootElement(name = "GetVServerStatusResponse")
+public class GetVServerStatusResponse extends StatusResponse implements
+        SingleElementResponse {
+    @XmlElement(required = true)
+    private VServerStatus vserverStatus;
+
+    @Override
+    public String toString() {
+        return getElement().toString();
+    }
+
+    @Override
+    public Object getElement() {
+        return vserverStatus;
+    }
+}
diff --git a/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/xml/internal/ListDiskImageResponse.java b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/xml/internal/ListDiskImageResponse.java
new file mode 100644
index 0000000..5e19ad6
--- /dev/null
+++ b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/xml/internal/ListDiskImageResponse.java
@@ -0,0 +1,49 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.fujitsu.fgcp.xml.internal;
+
+import java.util.Collections;
+import java.util.LinkedHashSet;
+import java.util.Set;
+
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlElementWrapper;
+import javax.xml.bind.annotation.XmlRootElement;
+
+import org.jclouds.fujitsu.fgcp.domain.DiskImage;
+
+import com.google.common.collect.ImmutableSet;
+
+/**
+ * Wrapper for ListDiskImageResponse.
+ * 
+ * @author Dies Koper
+ */
+@XmlRootElement(name = "ListDiskImageResponse")
+public class ListDiskImageResponse extends SetWithStatusResponse<DiskImage> {
+    @XmlElementWrapper(name = "diskimages")
+    @XmlElement(name = "diskimage")
+    private Set<DiskImage> diskImages = new LinkedHashSet<DiskImage>();
+
+    @Override
+    protected Set<DiskImage> delegate() {
+        return diskImages == null ? ImmutableSet.<DiskImage> of() : Collections
+                .unmodifiableSet(diskImages);
+    }
+}
diff --git a/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/xml/internal/ListEFMBackupResponse.java b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/xml/internal/ListEFMBackupResponse.java
new file mode 100644
index 0000000..a902625
--- /dev/null
+++ b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/xml/internal/ListEFMBackupResponse.java
@@ -0,0 +1,50 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.fujitsu.fgcp.xml.internal;
+
+import java.util.Collections;
+import java.util.LinkedHashSet;
+import java.util.Set;
+
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlElementWrapper;
+import javax.xml.bind.annotation.XmlRootElement;
+
+import org.jclouds.fujitsu.fgcp.domain.BuiltinServerBackup;
+
+import com.google.common.collect.ImmutableSet;
+
+/**
+ * Wrapper for ListEFMBackupResponse.
+ * 
+ * @author Dies Koper
+ */
+@XmlRootElement(name = "ListEFMBackupResponse")
+public class ListEFMBackupResponse extends
+        SetWithStatusResponse<BuiltinServerBackup> {
+    @XmlElementWrapper(name = "backups")
+    @XmlElement(name = "backup")
+    private Set<BuiltinServerBackup> backup = new LinkedHashSet<BuiltinServerBackup>();
+
+    @Override
+    protected Set<BuiltinServerBackup> delegate() {
+        return backup == null ? ImmutableSet.<BuiltinServerBackup> of()
+                : Collections.unmodifiableSet(backup);
+    }
+}
diff --git a/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/xml/internal/ListEFMResponse.java b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/xml/internal/ListEFMResponse.java
new file mode 100644
index 0000000..9ebbb1a
--- /dev/null
+++ b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/xml/internal/ListEFMResponse.java
@@ -0,0 +1,49 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.fujitsu.fgcp.xml.internal;
+
+import java.util.Collections;
+import java.util.LinkedHashSet;
+import java.util.Set;
+
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlElementWrapper;
+import javax.xml.bind.annotation.XmlRootElement;
+
+import org.jclouds.fujitsu.fgcp.domain.BuiltinServer;
+
+import com.google.common.collect.ImmutableSet;
+
+/**
+ * Wrapper for ListEFMResponse.
+ * 
+ * @author Dies Koper
+ */
+@XmlRootElement(name = "ListEFMResponse")
+public class ListEFMResponse extends SetWithStatusResponse<BuiltinServer> {
+    @XmlElementWrapper(name = "efms")
+    @XmlElement(name = "efm")
+    private Set<BuiltinServer> efm = new LinkedHashSet<BuiltinServer>();
+
+    @Override
+    protected Set<BuiltinServer> delegate() {
+        return efm == null ? ImmutableSet.<BuiltinServer> of() : Collections
+                .unmodifiableSet(efm);
+    }
+}
diff --git a/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/xml/internal/ListPublicIPResponse.java b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/xml/internal/ListPublicIPResponse.java
new file mode 100644
index 0000000..2b6c1a1
--- /dev/null
+++ b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/xml/internal/ListPublicIPResponse.java
@@ -0,0 +1,70 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.fujitsu.fgcp.xml.internal;
+
+import java.util.Collections;
+import java.util.Map;
+import java.util.Set;
+
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlElementWrapper;
+import javax.xml.bind.annotation.XmlRootElement;
+
+import org.jclouds.fujitsu.fgcp.domain.PublicIP;
+
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableMap.Builder;
+import com.google.common.collect.ImmutableSet;
+
+/**
+ * Wrapper for ListPublicIPResponse.
+ * 
+ * @author Dies Koper
+ */
+@XmlRootElement(name = "ListPublicIPResponse")
+public class ListPublicIPResponse extends
+        MapWithStatusResponse<PublicIP, String> implements
+        SingleElementResponse {
+    @XmlElementWrapper(name = "publicips")
+    @XmlElement(name = "publicip")
+    private Set<PublicIPWithSystemId> ips;
+
+    @Override
+    public String toString() {
+        return getElement().toString();
+    }
+
+    @Override
+    protected Map<PublicIP, String> delegate() {
+        Builder<PublicIP, String> returnVal = ImmutableMap.builder();
+        if (ips != null) {
+
+            for (PublicIPWithSystemId ip : ips) {
+                returnVal.put(ip, ip.getVsysId());
+            }
+        }
+        return returnVal.build();
+    }
+
+    @Override
+    public Set<? extends PublicIP> getElement() {
+        return ips == null ? ImmutableSet.<PublicIP> of() : Collections
+                .unmodifiableSet(ips);
+    }
+}
diff --git a/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/xml/internal/ListServerTypeResponse.java b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/xml/internal/ListServerTypeResponse.java
new file mode 100644
index 0000000..6d1e49e
--- /dev/null
+++ b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/xml/internal/ListServerTypeResponse.java
@@ -0,0 +1,48 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.fujitsu.fgcp.xml.internal;
+
+import java.util.Collections;
+import java.util.Set;
+
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlElementWrapper;
+import javax.xml.bind.annotation.XmlRootElement;
+
+import org.jclouds.fujitsu.fgcp.domain.ServerType;
+
+import com.google.common.collect.ImmutableSet;
+
+/**
+ * Wrapper for ListServerTypeResponse.
+ * 
+ * @author Dies Koper
+ */
+@XmlRootElement(name = "ListServerTypeResponse")
+public class ListServerTypeResponse extends SetWithStatusResponse<ServerType> {
+    @XmlElementWrapper(name = "servertypes")
+    @XmlElement(name = "servertype")
+    private Set<ServerType> serverTypes;
+
+    @Override
+    protected Set<ServerType> delegate() {
+        return serverTypes == null ? ImmutableSet.<ServerType> of()
+                : Collections.unmodifiableSet(serverTypes);
+    }
+}
diff --git a/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/xml/internal/ListVDiskResponse.java b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/xml/internal/ListVDiskResponse.java
new file mode 100644
index 0000000..0489a93
--- /dev/null
+++ b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/xml/internal/ListVDiskResponse.java
@@ -0,0 +1,49 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.fujitsu.fgcp.xml.internal;
+
+import java.util.Collections;
+import java.util.LinkedHashSet;
+import java.util.Set;
+
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlElementWrapper;
+import javax.xml.bind.annotation.XmlRootElement;
+
+import org.jclouds.fujitsu.fgcp.domain.VDisk;
+
+import com.google.common.collect.ImmutableSet;
+
+/**
+ * Wrapper for ListVDiskResponse.
+ * 
+ * @author Dies Koper
+ */
+@XmlRootElement(name = "ListVDiskResponse")
+public class ListVDiskResponse extends SetWithStatusResponse<VDisk> {
+    @XmlElementWrapper(name = "vdisks")
+    @XmlElement(name = "vdisk")
+    private Set<VDisk> disks = new LinkedHashSet<VDisk>();
+
+    @Override
+    protected Set<VDisk> delegate() {
+        return disks == null ? ImmutableSet.<VDisk> of() : Collections
+                .unmodifiableSet(disks);
+    }
+}
diff --git a/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/xml/internal/ListVSYSResponse.java b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/xml/internal/ListVSYSResponse.java
new file mode 100644
index 0000000..90826f6
--- /dev/null
+++ b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/xml/internal/ListVSYSResponse.java
@@ -0,0 +1,49 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.fujitsu.fgcp.xml.internal;
+
+import java.util.Collections;
+import java.util.LinkedHashSet;
+import java.util.Set;
+
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlElementWrapper;
+import javax.xml.bind.annotation.XmlRootElement;
+
+import org.jclouds.fujitsu.fgcp.domain.VSystem;
+
+import com.google.common.collect.ImmutableSet;
+
+/**
+ * Wrapper for ListVSYSResponse.
+ * 
+ * @author Dies Koper
+ */
+@XmlRootElement(name = "ListVSYSResponse")
+public class ListVSYSResponse extends SetWithStatusResponse<VSystem> {
+    @XmlElementWrapper(name = "vsyss")
+    @XmlElement(name = "vsys")
+    private Set<VSystem> systems = new LinkedHashSet<VSystem>();
+
+    @Override
+    protected Set<VSystem> delegate() {
+        return systems == null ? ImmutableSet.<VSystem> of() : Collections
+                .unmodifiableSet(systems);
+    }
+}
diff --git a/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/xml/internal/ListVServerResponse.java b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/xml/internal/ListVServerResponse.java
new file mode 100644
index 0000000..802a779
--- /dev/null
+++ b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/xml/internal/ListVServerResponse.java
@@ -0,0 +1,49 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.fujitsu.fgcp.xml.internal;
+
+import java.util.Collections;
+import java.util.LinkedHashSet;
+import java.util.Set;
+
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlElementWrapper;
+import javax.xml.bind.annotation.XmlRootElement;
+
+import org.jclouds.fujitsu.fgcp.domain.VServer;
+
+import com.google.common.collect.ImmutableSet;
+
+/**
+ * Wrapper for ListVServerResponse.
+ * 
+ * @author Dies Koper
+ */
+@XmlRootElement(name = "ListVServerResponse")
+public class ListVServerResponse extends SetWithStatusResponse<VServer> {
+    @XmlElementWrapper(name = "vservers")
+    @XmlElement(name = "vserver")
+    private Set<VServer> servers = new LinkedHashSet<VServer>();
+
+    @Override
+    protected Set<VServer> delegate() {
+        return servers == null ? ImmutableSet.<VServer> of() : Collections
+                .unmodifiableSet(servers);
+    }
+}
diff --git a/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/xml/internal/MapWithStatusResponse.java b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/xml/internal/MapWithStatusResponse.java
new file mode 100644
index 0000000..ffc5430
--- /dev/null
+++ b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/xml/internal/MapWithStatusResponse.java
@@ -0,0 +1,58 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.fujitsu.fgcp.xml.internal;
+
+import com.google.common.collect.ForwardingMap;
+
+import javax.xml.bind.annotation.XmlElement;
+
+/**
+ * Special base class extending (forwardable) Map with fields for the elements
+ * that FGCP XML responses specify.
+ * <p>
+ * This is useful for methods that return a set of elements that are better
+ * represented as key value pairs.
+ * 
+ * @author Dies Koper
+ */
+public abstract class MapWithStatusResponse<K, V> extends ForwardingMap<K, V>
+        implements StatusQuerable {
+    @XmlElement(required = true)
+    private String responseMessage;
+    @XmlElement(required = true)
+    private String responseStatus;
+
+    public String getResponseMessage() {
+        return responseMessage;
+    }
+
+    public String getResponseStatus() {
+        return responseStatus;
+    }
+
+    public boolean isError() {
+        return !"SUCCESS".equals(responseStatus);
+    }
+
+    @Override
+    public String toString() {
+        return "StatusResponse{" + "responseMessage='" + responseMessage + '\''
+                + ", responseStatus='" + responseStatus + '\'' + '}';
+    }
+}
diff --git a/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/xml/internal/PublicIPWithSystemId.java b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/xml/internal/PublicIPWithSystemId.java
new file mode 100644
index 0000000..fd9f18c
--- /dev/null
+++ b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/xml/internal/PublicIPWithSystemId.java
@@ -0,0 +1,43 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.fujitsu.fgcp.xml.internal;
+
+import javax.xml.bind.annotation.XmlRootElement;
+
+import org.jclouds.fujitsu.fgcp.domain.PublicIP;
+
+/**
+ * Represents a public IP address with its system id.
+ * 
+ * @author Dies Koper
+ */
+@XmlRootElement(name = "publicip")
+public class PublicIPWithSystemId extends PublicIP {
+    private String vsysId;
+
+    public String getVsysId() {
+        return vsysId;
+    }
+
+    @Override
+    public String toString() {
+        return "PublicIP{" + "address='" + address + '\'' + ", IP version='"
+                + version + '\'' + ", vsysId='" + vsysId + '\'' + '}';
+    }
+}
diff --git a/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/xml/internal/SetWithStatusResponse.java b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/xml/internal/SetWithStatusResponse.java
new file mode 100644
index 0000000..bb7158f
--- /dev/null
+++ b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/xml/internal/SetWithStatusResponse.java
@@ -0,0 +1,58 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.fujitsu.fgcp.xml.internal;
+
+import com.google.common.collect.ForwardingSet;
+
+import javax.xml.bind.annotation.XmlElement;
+
+/**
+ * Special base class extending (forwardable) Set with fields for the elements
+ * that FGCP XML responses specify.
+ * <p>
+ * This is useful for methods that return a Set and the XML response has no
+ * other elements but the set of elements (and message and status of course).
+ * 
+ * @author Dies Koper
+ */
+public abstract class SetWithStatusResponse<T> extends ForwardingSet<T>
+        implements StatusQuerable {
+    @XmlElement(required = true)
+    private String responseMessage;
+    @XmlElement(required = true)
+    private String responseStatus;
+
+    public String getResponseMessage() {
+        return responseMessage;
+    }
+
+    public String getResponseStatus() {
+        return responseStatus;
+    }
+
+    public boolean isError() {
+        return !"SUCCESS".equals(responseStatus);
+    }
+
+    @Override
+    public String toString() {
+        return delegate().toString();
+    }
+
+}
diff --git a/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/xml/internal/SingleElementResponse.java b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/xml/internal/SingleElementResponse.java
new file mode 100644
index 0000000..759586f
--- /dev/null
+++ b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/xml/internal/SingleElementResponse.java
@@ -0,0 +1,29 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.fujitsu.fgcp.xml.internal;
+
+/**
+ * Wrapper for CreateVSYSResponse.
+ * 
+ * @author Dies Koper
+ */
+public interface SingleElementResponse {
+
+    Object getElement();
+}
diff --git a/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/xml/internal/StatusQuerable.java b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/xml/internal/StatusQuerable.java
new file mode 100644
index 0000000..9046c68
--- /dev/null
+++ b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/xml/internal/StatusQuerable.java
@@ -0,0 +1,32 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.fujitsu.fgcp.xml.internal;
+
+/**
+ * Exposes methods to obtain the status and message from the API server.
+ * 
+ * @author Dies Koper
+ */
+public interface StatusQuerable {
+    public String getResponseMessage();
+
+    public String getResponseStatus();
+
+    public boolean isError();
+}
diff --git a/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/xml/internal/StatusResponse.java b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/xml/internal/StatusResponse.java
new file mode 100644
index 0000000..7ea3361
--- /dev/null
+++ b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/xml/internal/StatusResponse.java
@@ -0,0 +1,60 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.fujitsu.fgcp.xml.internal;
+
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+
+/**
+ * Base class with fields for the elements that FGCP XML responses specify.
+ * 
+ * @author Dies Koper
+ */
+public abstract class StatusResponse implements StatusQuerable {
+    @XmlElement(required = true)
+    private String responseMessage;
+    @XmlElement(required = true)
+    private String responseStatus;
+
+    public String getResponseMessage() {
+        return responseMessage;
+    }
+
+    public void setResponseMessage(String responseMessage) {
+        this.responseMessage = responseMessage;
+    }
+
+    public String getResponseStatus() {
+        return responseStatus;
+    }
+
+    public void setResponseStatus(String responseStatus) {
+        this.responseStatus = responseStatus;
+    }
+
+    public boolean isError() {
+        return !"SUCCESS".equals(responseStatus);
+    }
+
+    @Override
+    public String toString() {
+        return "StatusResponse{" + "responseMessage='" + responseMessage + '\''
+                + ", responseStatus='" + responseStatus + '\'' + '}';
+    }
+}
diff --git a/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/xml/internal/package-info.java b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/xml/internal/package-info.java
new file mode 100644
index 0000000..12b705b
--- /dev/null
+++ b/labs/fgcp/src/main/java/org/jclouds/fujitsu/fgcp/xml/internal/package-info.java
@@ -0,0 +1,28 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+@XmlSchema(namespace = "http://apioviss.jp.fujitsu.com", elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED)
+//@XmlJavaTypeAdapter(value=SetOfServerTypesXMLAdapter.class,type= Set.class)
+//@XmlJavaTypeAdapter(value=SetOfServerTypesXMLAdapter.class,type= ListServerTypeResponse.class)
+@XmlAccessorType(XmlAccessType.FIELD)
+package org.jclouds.fujitsu.fgcp.xml.internal;
+
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlSchema;
+
diff --git a/labs/fgcp/src/main/resources/META-INF/services/org.jclouds.apis.ApiMetadata b/labs/fgcp/src/main/resources/META-INF/services/org.jclouds.apis.ApiMetadata
new file mode 100644
index 0000000..f2a75c0
--- /dev/null
+++ b/labs/fgcp/src/main/resources/META-INF/services/org.jclouds.apis.ApiMetadata
@@ -0,0 +1 @@
+org.jclouds.fujitsu.fgcp.FGCPApiMetadata
\ No newline at end of file
diff --git a/labs/fgcp/src/main/resources/org/jclouds/fujitsu/fgcp/domain/jaxb.index b/labs/fgcp/src/main/resources/org/jclouds/fujitsu/fgcp/domain/jaxb.index
new file mode 100644
index 0000000..4917877
--- /dev/null
+++ b/labs/fgcp/src/main/resources/org/jclouds/fujitsu/fgcp/domain/jaxb.index
@@ -0,0 +1,45 @@
+#listing of all classes in the domain package (at this time of writing)
+#as some or all are likely to contain JAXB annotations
+#note that even if (newer) classes are missing, as long as they are statically referenced from
+#any of these classes they'll be included in the JAXB context.
+AddressRange
+BuiltinServer
+BuiltinServerStatus
+Cause
+CPU
+Direction
+Disk
+DiskImage
+ErrorStatistics
+EventLog
+Firewall
+Group
+Image
+Information
+IntermediateCACert
+LoadStatistics
+Memory
+NAT
+PerformanceInfo
+Period
+Policy
+Product
+PublicIPStatus
+Rule
+ServerCert
+ServerType
+SLB
+Software
+Target
+UsageInfo
+VDisk
+VDiskStatus
+VNet
+VNIC
+VServer
+VServerStatus
+VServerWithDetails
+VSystem
+VSystemDescriptor
+VSystemStatus
+VSystemWithDetails
\ No newline at end of file
diff --git a/labs/fgcp/src/main/resources/org/jclouds/fujitsu/fgcp/xml/internal/jaxb.index b/labs/fgcp/src/main/resources/org/jclouds/fujitsu/fgcp/xml/internal/jaxb.index
new file mode 100644
index 0000000..3e4a1e8
--- /dev/null
+++ b/labs/fgcp/src/main/resources/org/jclouds/fujitsu/fgcp/xml/internal/jaxb.index
@@ -0,0 +1,30 @@
+#listing of all classes in the xml.internal package (at this time of writing)
+CreateVDiskResponse
+CreateEFMResponse
+CreateVServerResponse
+CreateVSYSResponse
+GetAddressRangeResponse
+GetDiskImageAttributesResponse
+GetEFMAttributesResponse
+GetEFMStatusResponse
+GetEventLogResponse
+GetPublicIPAttributesResponse
+GetPublicIPStatusResponse
+GetVDiskAttributesResponse
+GetVServerAttributesResponse
+GetVServerConfigurationResponse
+GetVServerInitialPasswordResponse
+GetVServerStatusResponse
+GetVSYSAttributesResponse
+GetVSYSConfigurationResponse
+GetVSYSDescriptorConfigurationResponse
+GetVSYSStatusResponse
+ListDiskImageResponse
+ListEFMBackupResponse
+ListEFMResponse
+ListPublicIPResponse
+ListServerTypeResponse
+ListVDiskResponse
+ListVServerResponse
+ListVSYSResponse
+PublicIPWithSystemId
diff --git a/labs/fgcp/src/test/java/org/jclouds/fujitsu/fgcp/compute/FGCPBaseTemplateBuilderLiveTest.java b/labs/fgcp/src/test/java/org/jclouds/fujitsu/fgcp/compute/FGCPBaseTemplateBuilderLiveTest.java
new file mode 100644
index 0000000..54388cd
--- /dev/null
+++ b/labs/fgcp/src/test/java/org/jclouds/fujitsu/fgcp/compute/FGCPBaseTemplateBuilderLiveTest.java
@@ -0,0 +1,84 @@
+package org.jclouds.fujitsu.fgcp.compute;
+
+import static org.jclouds.compute.util.ComputeServiceUtils.getCores;
+import static org.testng.Assert.assertEquals;
+
+import java.io.IOException;
+import java.util.Properties;
+
+import org.jclouds.Constants;
+import org.jclouds.compute.domain.OsFamily;
+import org.jclouds.compute.domain.OsFamilyVersion64Bit;
+import org.jclouds.compute.domain.Template;
+import org.jclouds.compute.internal.BaseTemplateBuilderLiveTest;
+
+import com.google.common.base.Predicate;
+import com.google.common.base.Predicates;
+
+public abstract class FGCPBaseTemplateBuilderLiveTest extends
+        BaseTemplateBuilderLiveTest {
+
+    @Override
+    protected Properties setupProperties() {
+        Properties overrides = super.setupProperties();
+
+        String proxy = System.getenv("http_proxy");
+        if (proxy != null) {
+
+            String[] parts = proxy.split("http://|:|@");
+
+            overrides.setProperty(Constants.PROPERTY_PROXY_HOST,
+                    parts[parts.length - 2]);
+            overrides.setProperty(Constants.PROPERTY_PROXY_PORT,
+                    parts[parts.length - 1]);
+
+            if (parts.length >= 4) {
+                overrides.setProperty(Constants.PROPERTY_PROXY_USER,
+                        parts[parts.length - 4]);
+                overrides.setProperty(Constants.PROPERTY_PROXY_PASSWORD,
+                        parts[parts.length - 3]);
+            }
+        }
+
+        // enables peer verification using the CAs bundled with the JRE (or
+        // value of javax.net.ssl.trustStore if set)
+        overrides.setProperty(Constants.PROPERTY_TRUST_ALL_CERTS, "false");
+
+        return overrides;
+    }
+
+    @Override
+    protected Predicate<OsFamilyVersion64Bit> defineUnsupportedOperatingSystems() {
+        return Predicates.not(new Predicate<OsFamilyVersion64Bit>() {
+
+            @Override
+            public boolean apply(OsFamilyVersion64Bit input) {
+                switch (input.family) {
+                case CENTOS:
+                    return input.version.matches("5.[46]")
+                            || input.version.equals("6.[2]");
+                case WINDOWS:
+                    return (input.version.equals("2008 R2 SE") || input.version
+                            .equals("2008 R2 EE")) && input.is64Bit;
+                default:
+                    return false;
+                }
+            }
+
+        });
+    }
+
+    public void testDefaultTemplateBuilder() throws IOException {
+        Template defaultTemplate = view.getComputeService().templateBuilder()
+                .build();
+        assert defaultTemplate.getImage().getOperatingSystem().getVersion()
+                .matches("6.2") : defaultTemplate.getImage()
+                .getOperatingSystem().getVersion();
+        assertEquals(defaultTemplate.getImage().getOperatingSystem().is64Bit(),
+                true);
+        assertEquals(defaultTemplate.getImage().getOperatingSystem()
+                .getFamily(), OsFamily.CENTOS);
+        assertEquals(getCores(defaultTemplate.getHardware()), 1.0d);
+    }
+
+}
\ No newline at end of file
diff --git a/labs/fgcp/src/test/java/org/jclouds/fujitsu/fgcp/compute/FGCPRestClientModuleTest.java b/labs/fgcp/src/test/java/org/jclouds/fujitsu/fgcp/compute/FGCPRestClientModuleTest.java
new file mode 100644
index 0000000..9c1c880
--- /dev/null
+++ b/labs/fgcp/src/test/java/org/jclouds/fujitsu/fgcp/compute/FGCPRestClientModuleTest.java
@@ -0,0 +1,98 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.fujitsu.fgcp.compute;
+
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+import org.jclouds.crypto.Crypto;
+import org.jclouds.fujitsu.fgcp.FGCPApiMetadata;
+
+import org.testng.annotations.BeforeTest;
+import org.testng.annotations.Test;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.URL;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.cert.CertificateException;
+import java.security.spec.InvalidKeySpecException;
+import java.util.Scanner;
+
+import static org.testng.Assert.*;
+
+/**
+ * @author Dies Koper
+ */
+@Test(groups = "unit", testName = "FGCPRestClientModuleTest")
+public class FGCPRestClientModuleTest {
+
+    protected FGCPRestClientModule module;
+    protected Crypto crypto;
+
+    @BeforeTest
+    protected void createCrypto() {
+        Injector i = Guice.createInjector();
+        crypto = i.getInstance(Crypto.class);
+    }
+
+    @BeforeTest
+    protected void createRestClientModule() {
+        Injector i = Guice.createInjector();
+        module = i.getInstance(FGCPRestClientModule.class);
+    }
+
+    public void testKeyStoreAsPkcs12() throws IOException, InvalidKeySpecException, NoSuchAlgorithmException, KeyStoreException, CertificateException {
+        assertNotNull(crypto);
+        assertNotNull(module);
+
+        // self-signed dummy cert:
+        // keytool -genkey -alias test-fgcp -keyalg RSA -keysize 1024 -validity 5475 -dname "CN=localhost" -keystore jclouds-test-fgcp.p12 -storepass jcloudsjclouds -storetype pkcs12
+        String cert = "/certs/jclouds-test-fgcp.p12";
+        String keyPassword = "jcloudsjclouds";
+
+        URL url = this.getClass().getResource(cert);
+        String certPath = url.getFile();
+
+        KeyStore ks = module.provideKeyStore(crypto, certPath, keyPassword);
+
+        assertNotNull(ks.getCertificate("test-fgcp"), "cert with alias");
+    }
+
+/*    public void testKeyStoreAsPEM() throws IOException, InvalidKeySpecException, NoSuchAlgorithmException, KeyStoreException, CertificateException {
+        assertNotNull(crypto);
+        assertNotNull(module);
+
+        //openssl pkcs12 -nodes -in jclouds-test-fgcp.p12 -out jclouds-test-fgcp.pem
+//        String privKeyFilename = "D:\\UserCert.pem.pkcs12-nodes";//_nobags";
+        String cert = "/certs/jclouds-test-fgcp.pem";
+        String keyPassword = "jcloudsjclouds";
+
+        URL url = this.getClass().getResource(cert);
+        String certPath = url.getFile();
+        Scanner scanner = new Scanner(new File(certPath));
+        String content = scanner.useDelimiter("\\A").next();
+
+        KeyStore ks = module.provideKeyStore(crypto, content, keyPassword);
+
+        assertNotNull(ks.getCertificate("test-fgcp"), "cert with alias");
+    }
+*/
+}
diff --git a/labs/fgcp/src/test/java/org/jclouds/fujitsu/fgcp/compute/config/FGCPBaseComputeServiceLiveTest.java b/labs/fgcp/src/test/java/org/jclouds/fujitsu/fgcp/compute/config/FGCPBaseComputeServiceLiveTest.java
new file mode 100644
index 0000000..996965b
--- /dev/null
+++ b/labs/fgcp/src/test/java/org/jclouds/fujitsu/fgcp/compute/config/FGCPBaseComputeServiceLiveTest.java
@@ -0,0 +1,187 @@
+package org.jclouds.fujitsu.fgcp.compute.config;
+
+import java.util.Properties;
+
+import org.jclouds.Constants;
+import org.jclouds.compute.domain.ExecResponse;
+import org.jclouds.compute.domain.NodeMetadata;
+import org.jclouds.compute.internal.BaseComputeServiceLiveTest;
+import org.jclouds.rest.AuthorizationException;
+import org.jclouds.sshj.config.SshjSshClientModule;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+import com.google.inject.Module;
+
+public abstract class FGCPBaseComputeServiceLiveTest extends
+        BaseComputeServiceLiveTest {
+
+    @Override
+    protected Properties setupProperties() {
+        Properties overrides = super.setupProperties();
+    
+        String proxy = System.getenv("http_proxy");
+        if (proxy != null) {
+    
+            String[] parts = proxy.split("http://|:|@");
+    
+            overrides.setProperty(Constants.PROPERTY_PROXY_HOST, parts[parts.length - 2]);
+            overrides.setProperty(Constants.PROPERTY_PROXY_PORT, parts[parts.length - 1]);
+    
+            if (parts.length >= 4) {
+                overrides.setProperty(Constants.PROPERTY_PROXY_USER, parts[parts.length - 4]);
+                overrides.setProperty(Constants.PROPERTY_PROXY_PASSWORD, parts[parts.length - 3]);
+            }
+        }
+    
+        // enables peer verification using the CAs bundled with the JRE (or
+        // value of javax.net.ssl.trustStore if set)
+        overrides.setProperty(Constants.PROPERTY_TRUST_ALL_CERTS, "false");
+    
+        return overrides;
+    }
+
+    @Override
+    protected Module getSshModule() {
+       return new SshjSshClientModule();
+    }
+
+    @Override
+    @Test(enabled = false, expectedExceptions = AuthorizationException.class)
+    public void testCorrectAuthException() throws Exception {
+        // http://code.google.com/p/jclouds/issues/detail?id=1060
+    }
+
+    // fgcp does not support metadata
+    @Override
+    protected void checkUserMetadataInNodeEquals(NodeMetadata node, ImmutableMap<String, String> userMetadata) {
+        assert node.getUserMetadata().isEmpty() : String.format(
+                "node userMetadata not empty: %s %s", node,
+                node.getUserMetadata());
+     }
+
+    // node name can't be retrieved through the API and is therefore null
+    protected void checkResponseEqualsHostname(ExecResponse execResponse,
+            NodeMetadata node) {
+        assert node.getHostname() == null : node + " with hostname: "
+                + node.getHostname();
+    }
+
+    // tags are not (yet) supported for fgcp
+    protected void checkTagsInNodeEquals(NodeMetadata node,
+            ImmutableSet<String> tags) {
+        assert node.getTags().isEmpty() : String.format(
+                "node tags found %s (%s) in node %s", node.getTags(), tags, node);
+    }
+
+    /*
+     * public void testCreateAndRunAService() throws Exception {
+     * super.testCreateAndRunAService(); }
+     */
+
+    // this test requires network access to the VM it creates:
+    // before running it, start an SSL/VPN connection to the last updated vsys'
+    // DMZ.
+    // may also need to configure SNAT and FW rules to allow the VM to
+    // communicate out (53 for DNS, 80 for yum).
+    public void testAScriptExecutionAfterBootWithBasicTemplate()
+            throws Exception {
+        super.testAScriptExecutionAfterBootWithBasicTemplate();
+    }
+
+    @Override
+    @Test(enabled = false)
+    public void testOptionToNotBlock() throws Exception {
+        // start call returns before node reaches running state, but
+        // test may be failing due to the system being in a 're-configuring'
+        // state while destroying nodes of a previous test.
+        // http://code.google.com/p/jclouds/issues/detail?id=1066
+            /*
+    org.jclouds.compute.RunNodesException: error running 1 node group(fgcp-aublock) location(UZXC0GRT-IZKDVGIL5-N-SECURE1) image(IMG_3c9820_71OW9NZC268) size(islanda-cbrm_140) options({inboundPorts=[], blockUntilRunning=false})
+    Execution failures:
+    
+    1) ExecutionException on fgcp-aublock-787:
+    java.util.concurrent.ExecutionException: java.lang.IllegalStateException: The status of Instance[UZXC0GRT-IZKDVGIL5] is [RECONFIG_ING].
+        at com.google.common.util.concurrent.AbstractFuture$Sync.getValue(AbstractFuture.java:289)
+        at com.google.common.util.concurrent.AbstractFuture$Sync.get(AbstractFuture.java:276)
+        at com.google.common.util.concurrent.AbstractFuture.get(AbstractFuture.java:111)
+        at org.jclouds.concurrent.FutureIterables$1.run(FutureIterables.java:134)
+        at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(Unknown Source)
+        at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
+        at java.lang.Thread.run(Unknown Source)
+    Caused by: java.lang.IllegalStateException: The status of Instance[UZXC0GRT-IZKDVGIL5] is [RECONFIG_ING].
+        at org.jclouds.fujitsu.fgcp.xml.FGCPJAXBParser.fromXML(FGCPJAXBParser.java:75)
+        at org.jclouds.http.functions.ParseXMLWithJAXB.apply(ParseXMLWithJAXB.java:91)
+        at org.jclouds.http.functions.ParseXMLWithJAXB.apply(ParseXMLWithJAXB.java:86)
+        at org.jclouds.http.functions.ParseXMLWithJAXB.apply(ParseXMLWithJAXB.java:73)
+        at org.jclouds.http.functions.ParseXMLWithJAXB.apply(ParseXMLWithJAXB.java:54)
+        at com.google.common.base.Functions$FunctionComposition.apply(Functions.java:209)
+        at com.google.common.util.concurrent.Futures$3.apply(Futures.java:380)
+        at com.google.common.util.concurrent.Futures$ChainingListenableFuture.run(Futures.java:522)
+        at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(Unknown Source)
+        at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
+        at java.lang.Thread.run(Unknown Source)
+        at org.jclouds.concurrent.config.DescribingExecutorService.submit(DescribingExecutorService.java:89)
+        at org.jclouds.compute.strategy.impl.CreateNodesWithGroupEncodedIntoNameThenAddToSet.createNodeInGroupWithNameAndTemplate(CreateNodesWithGroupEncodedIntoNameThenAddToSet.java:170)
+        at org.jclouds.compute.strategy.impl.CreateNodesWithGroupEncodedIntoNameThenAddToSet.execute(CreateNodesWithGroupEncodedIntoNameThenAddToSet.java:125)
+        at org.jclouds.compute.internal.BaseComputeService.createNodesInGroup(BaseComputeService.java:213)
+        at org.jclouds.compute.internal.BaseComputeService.createNodesInGroup(BaseComputeService.java:229)
+        at org.jclouds.compute.internal.BaseComputeServiceLiveTest.testOptionToNotBlock(BaseComputeServiceLiveTest.java:803)
+             */
+        }
+
+/*    @Override
+    @Test(enabled = false)
+    public void testCreateTwoNodesWithRunScript() {
+    }
+
+    @Override
+    @Test(enabled = false)
+    public void testCreateAnotherNodeWithANewContextToEnsureSharedMemIsntRequired() {
+    }
+
+    @Override
+    @Test(enabled = false)
+    public void testGet() {
+    }
+*/
+//    @Override
+//    @Test(enabled = false)
+//    public void testConcurrentUseOfComputeServiceToCreateNodes() throws Exception {
+        // http://code.google.com/p/jclouds/issues/detail?id=1066
+        /*
+        1) ExecutionException on twin0-f6a:
+            java.util.concurrent.ExecutionException: org.jclouds.http.HttpResponseException: Error parsing input
+            {statusCode=200, message=OK, headers={Date=[Sun, 26 Aug 2012 01:22:50 GMT], Transfer-Encoding=[chunked], Set-Cookie=[JSESSIONID=8A07404DF0405E46B3A748C3763B0D9F; Path=/ovisspxy; Secure], Connection=[close]}, payload=[content=true, contentMetadata=[contentDisposition=null, contentEncoding=null, contentLanguage=null, contentLength=null, contentMD5=null, contentType=text/xml;charset=UTF-8, expires=null], written=false]}
+                at com.google.common.util.concurrent.AbstractFuture$Sync.getValue(AbstractFuture.java:289)
+                at com.google.common.util.concurrent.AbstractFuture$Sync.get(AbstractFuture.java:276)
+                at com.google.common.util.concurrent.AbstractFuture.get(AbstractFuture.java:111)
+                at org.jclouds.concurrent.FutureIterables$1.run(FutureIterables.java:134)
+                at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(Unknown Source)
+                at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
+                at java.lang.Thread.run(Unknown Source)
+            Caused by: org.jclouds.http.HttpResponseException: Error parsing input
+            {statusCode=200, message=OK, headers={Date=[Sun, 26 Aug 2012 01:22:50 GMT], Transfer-Encoding=[chunked], Set-Cookie=[JSESSIONID=8A07404DF0405E46B3A748C3763B0D9F; Path=/ovisspxy; Secure], Connection=[close]}, payload=[content=true, contentMetadata=[contentDisposition=null, contentEncoding=null, contentLanguage=null, contentLength=null, contentMD5=null, contentType=text/xml;charset=UTF-8, expires=null], written=false]}
+                at org.jclouds.http.functions.ParseXMLWithJAXB.apply(ParseXMLWithJAXB.java:78)
+                at org.jclouds.http.functions.ParseXMLWithJAXB.apply(ParseXMLWithJAXB.java:1)
+                at com.google.common.base.Functions$FunctionComposition.apply(Functions.java:209)
+                at com.google.common.util.concurrent.Futures$3.apply(Futures.java:380)
+                at com.google.common.util.concurrent.Futures$ChainingListenableFuture.run(Futures.java:522)
+                at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(Unknown Source)
+                at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
+                at java.lang.Thread.run(Unknown Source)
+                at org.jclouds.concurrent.config.DescribingExecutorService.submit(DescribingExecutorService.java:89)
+                at org.jclouds.compute.strategy.impl.CreateNodesWithGroupEncodedIntoNameThenAddToSet.createNodeInGroupWithNameAndTemplate(CreateNodesWithGroupEncodedIntoNameThenAddToSet.java:170)
+                at org.jclouds.compute.strategy.impl.CreateNodesWithGroupEncodedIntoNameThenAddToSet.execute(CreateNodesWithGroupEncodedIntoNameThenAddToSet.java:125)
+                at org.jclouds.compute.internal.BaseComputeService.createNodesInGroup(BaseComputeService.java:213)
+                at org.jclouds.compute.internal.BaseComputeService.createNodesInGroup(BaseComputeService.java:229)
+                at org.jclouds.compute.internal.BaseComputeServiceLiveTest$1.call(BaseComputeServiceLiveTest.java:442)
+                at org.jclouds.compute.internal.BaseComputeServiceLiveTest$1.call(BaseComputeServiceLiveTest.java:1)
+                ... 3 more
+            Caused by: org.jclouds.http.HttpException: The status of Instance[UZXC0GRT-9Q988189J] is [RECONFIG_ING].
+                at org.jclouds.fujitsu.fgcp.xml.FGCPJAXBParser.fromXML(FGCPJAXBParser.java:81)
+                at org.jclouds.http.functions.ParseXMLWithJAXB.apply(ParseXMLWithJAXB.java:91)
+*/        
+//    }
+}
\ No newline at end of file
diff --git a/labs/fgcp/src/test/java/org/jclouds/fujitsu/fgcp/compute/functions/DiskImageToOperatingSystemTest.java b/labs/fgcp/src/test/java/org/jclouds/fujitsu/fgcp/compute/functions/DiskImageToOperatingSystemTest.java
new file mode 100644
index 0000000..966ea07
--- /dev/null
+++ b/labs/fgcp/src/test/java/org/jclouds/fujitsu/fgcp/compute/functions/DiskImageToOperatingSystemTest.java
@@ -0,0 +1,163 @@
+package org.jclouds.fujitsu.fgcp.compute.functions;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertNull;
+import static org.testng.Assert.assertTrue;
+
+import java.util.Arrays;
+import java.util.List;
+
+import org.jclouds.compute.domain.OperatingSystem;
+import org.jclouds.compute.domain.OsFamily;
+import org.jclouds.fujitsu.fgcp.compute.functions.DiskImageToOperatingSystem;
+import org.jclouds.fujitsu.fgcp.domain.DiskImage;
+import org.jclouds.fujitsu.fgcp.domain.DiskImage.Builder;
+import org.testng.annotations.Test;
+
+/**
+ * @author Dies Koper
+ */
+@Test(groups = "unit", testName = "DiskImageToOperatingSystemTest")
+public class DiskImageToOperatingSystemTest {
+    // Operating Systems available JAN 2012 (taken from osName)
+    private static final List<String> operatingSystems = Arrays.asList(
+            // JP
+            "CentOS 5.6 32bit (English)",
+            "CentOS 5.6 64bit (English)",
+            "Red Hat Enterprise Linux 5.5 32bit (Japanese)",
+            "Red Hat Enterprise Linux 5.5 64bit (Japanese)",
+            "Windows Server 2003 R2 EE 32bit SP2 (日本語版) サポート付",
+            "Windows Server 2003 R2 EE 32bit SP2 (日本語版)",
+            "Windows Server 2008 R2 EE 64bit (日本語版) サポート付",
+            "Windows Server 2008 R2 EE 64bit (日本語版)",
+            "Windows Server 2008 R2 SE 64bit (日本語版)  サポート付",
+            "Windows Server 2008 R2 SE 64bit (日本語版)",
+            "Windows Server 2008 SE 32bit SP2 (日本語版) サポート付",
+            "Windows Server 2008 SE 32bit SP2 (日本語版)",
+            // AU
+            "CentOS 5.4 64bit (English)", "CentOS 5.4 32bit (English)",
+            "Windows Server 2008 R2 SE 64bit (English)",
+            "Windows Server 2008 R2 EE 64bit (English)");
+
+    @Test
+    public void testConversion() {
+        for (String description : operatingSystems) {
+            Builder builder = DiskImage.builder();
+            builder.osName(description);
+            builder.osType("hvm");
+            builder.creatorName("creator");
+            builder.registrant("registrant");
+            builder.description("description");
+            builder.id("ABCDEFGH");
+            DiskImage image = builder.build();
+
+            OperatingSystem os = new DiskImageToOperatingSystem().apply(image);
+
+            assertNotNull(os, description);
+            assertNotNull(os.getFamily(), description);
+            assertFalse(os.getFamily().equals(OsFamily.UNRECOGNIZED),
+                    "OsFamily not recognised: " + description);
+            assertNotNull(os.getVersion(), "Version not recognised: "
+                    + description);
+            assertEquals(os.getName(), description);
+            assertEquals(os.getDescription(), description);
+            assertNotNull(os.getArch(), description);
+        }
+    }
+
+    @Test
+    public void testOsFamilyUnrecognized() {
+        DiskImage image = DiskImage.builder()
+                .osName("not a known operating system").build();
+
+        OperatingSystem os = new DiskImageToOperatingSystem().apply(image);
+
+        assertNotNull(os);
+        assertEquals(os.getFamily(), OsFamily.UNRECOGNIZED);
+    }
+
+    @Test
+    public void test64BitsWithSpace() {
+        DiskImage image = DiskImage.builder().osName("a (64 bit) os").build();
+
+        OperatingSystem os = new DiskImageToOperatingSystem().apply(image);
+
+        assertNotNull(os);
+        assertTrue(os.is64Bit());
+    }
+
+    @Test
+    public void test64BitsNoSpace() {
+        DiskImage image = DiskImage.builder().osName("a (64bit) os").build();
+
+        OperatingSystem os = new DiskImageToOperatingSystem().apply(image);
+
+        assertNotNull(os);
+        assertTrue(os.is64Bit());
+    }
+
+    @Test
+    public void test32BitsNoSpace() {
+        DiskImage image = DiskImage.builder().osName("a (32bit) os").build();
+
+        OperatingSystem os = new DiskImageToOperatingSystem().apply(image);
+
+        assertNotNull(os);
+        assertFalse(os.is64Bit());
+    }
+
+    @Test
+    public void testx64NoSpace() {
+        DiskImage image = DiskImage.builder().osName("a (x64) os").build();
+
+        OperatingSystem os = new DiskImageToOperatingSystem().apply(image);
+
+        assertNotNull(os);
+        assertTrue(os.is64Bit());
+    }
+
+    @Test
+    public void testWindowsVersion() {
+        DiskImage image = DiskImage.builder()
+                .osName("Windows Server 2008 R2 SE 64 bit").build();
+
+        OperatingSystem os = new DiskImageToOperatingSystem().apply(image);
+
+        assertNotNull(os);
+        assertEquals(os.getVersion(), "2008 R2 SE");
+    }
+
+    @Test
+    public void testCentOSVersion() {
+        DiskImage image = DiskImage.builder()
+                .osName("CentOS 6.2 64bit (English)").build();
+
+        OperatingSystem os = new DiskImageToOperatingSystem().apply(image);
+
+        assertNotNull(os);
+        assertEquals(os.getVersion(), "6.2");
+    }
+
+    @Test
+    public void testUnrecognizedOsVersion() {
+        DiskImage image = DiskImage.builder()
+                .osName("Windows Server 2099 (256 bit)").build();
+
+        OperatingSystem os = new DiskImageToOperatingSystem().apply(image);
+
+        assertNotNull(os);
+        assertNull(os.getVersion());
+    }
+
+    @Test
+    public void testOsVersionMissing() {
+        DiskImage image = DiskImage.builder().osName("asd Server").build();
+
+        OperatingSystem os = new DiskImageToOperatingSystem().apply(image);
+        assertNotNull(os);
+        assertNull(os.getVersion(), "os.getVersion(): \'" + os.getVersion()
+                + "\'");
+    }
+}
diff --git a/labs/fgcp/src/test/java/org/jclouds/fujitsu/fgcp/services/AdditionalDiskApiExpectTest.java b/labs/fgcp/src/test/java/org/jclouds/fujitsu/fgcp/services/AdditionalDiskApiExpectTest.java
new file mode 100644
index 0000000..953fceb
--- /dev/null
+++ b/labs/fgcp/src/test/java/org/jclouds/fujitsu/fgcp/services/AdditionalDiskApiExpectTest.java
@@ -0,0 +1,157 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.fujitsu.fgcp.services;
+
+import static org.testng.Assert.assertEquals;
+
+import org.jclouds.http.HttpRequest;
+import org.jclouds.http.HttpResponse;
+import org.testng.annotations.Test;
+
+/**
+ * @author Dies Koper
+ */
+@Test(groups = "unit", testName = "AdditionalDiskApiExpectTest", singleThreaded = true)
+public class AdditionalDiskApiExpectTest extends BaseFGCPRestApiExpectTest {
+
+    public void testGet() {
+        HttpRequest request = buildGETWithQuery("Action=GetVDiskAttributes"
+                + "&vdiskId=CONTRACT-VSYS00001-D-0001"
+                + "&vsysId=CONTRACT-VSYS00001");
+        HttpResponse response = HttpResponse
+                .builder()
+                .statusCode(200)
+                .payload(
+                        payloadFromResource("/GetVDiskAttributes-response.xml"))
+                .build();
+
+        AdditionalDiskApi api = requestSendsResponse(request, response)
+                .getAdditionalDiskApi();
+
+        assertEquals(api.get("CONTRACT-VSYS00001-D-0001").getSize(), 10.0);
+    }
+
+    public void testGetStatus() {
+        HttpRequest request = buildGETWithQuery("Action=GetVDiskStatus"
+                + "&vdiskId=CONTRACT-VSYS00001-S-0001"
+                + "&vsysId=CONTRACT-VSYS00001");
+        HttpResponse response = HttpResponse
+                .builder()
+                .statusCode(200)
+                .payload(
+                        payloadFromResource("/GetVDiskStatus-response.xml"))
+                .build();
+
+        AdditionalDiskApi api = requestSendsResponse(request, response)
+                .getAdditionalDiskApi();
+
+        // api is returning STOPPED which is not a documented status. Documentation error?
+//        assertEquals(api.getStatus("CONTRACT-VSYS00001-S-0001"), VDiskStatus.STOPPED);
+    }
+
+    public void testUpdate() {
+        HttpRequest request = buildGETWithQuery("Action=UpdateVDiskAttribute"
+                + "&vdiskId=CONTRACT-VSYS00001-D-0001"
+                + "&attributeValue=new-name" + "&attributeName=updateName"
+                + "&vsysId=CONTRACT-VSYS00001");
+        HttpResponse response = HttpResponse
+                .builder()
+                .statusCode(200)
+                .payload(
+                        payloadFromResource("/UpdateVDiskAttribute-response.xml"))
+                .build();
+
+        AdditionalDiskApi api = requestSendsResponse(request, response)
+                .getAdditionalDiskApi();
+
+        api.update("CONTRACT-VSYS00001-D-0001", "updateName", "new-name");
+    }
+
+    public void testDestroy() {
+        HttpRequest request = buildGETWithQuery("Action=DestroyVDisk"
+                + "&vdiskId=CONTRACT-VSYS00001-D-0001"
+                + "&vsysId=CONTRACT-VSYS00001");
+        HttpResponse response = HttpResponse.builder().statusCode(200)
+                .payload(payloadFromResource("/DestroyVDisk-response.xml"))
+                .build();
+
+        AdditionalDiskApi api = requestSendsResponse(request, response)
+                .getAdditionalDiskApi();
+
+        api.destroy("CONTRACT-VSYS00001-D-0001");
+    }
+
+    public void testBackup() {
+        HttpRequest request = buildGETWithQuery("Action=BackupVDisk"
+                + "&vdiskId=CONTRACT-VSYS00001-D-0001"
+                + "&vsysId=CONTRACT-VSYS00001");
+        HttpResponse response = HttpResponse.builder().statusCode(200)
+                .payload(payloadFromResource("/BackupVDisk-response.xml"))
+                .build();
+
+        AdditionalDiskApi api = requestSendsResponse(request, response)
+                .getAdditionalDiskApi();
+
+        api.backup("CONTRACT-VSYS00001-D-0001");
+    }
+
+    public void testRestore() {
+        HttpRequest request = buildGETWithQuery("Action=RestoreVDisk"
+                + "&vsysId=CONTRACT-VSYS00001"
+                + "&backupId=003");
+        HttpResponse response = HttpResponse.builder().statusCode(200)
+                .payload(payloadFromResource("/RestoreVDisk-response.xml"))
+                .build();
+
+        AdditionalDiskApi api = requestSendsResponse(request, response)
+                .getAdditionalDiskApi();
+
+        api.restore("CONTRACT-VSYS00001", "003");
+    }
+
+    public void testDetach() {
+        HttpRequest request = buildGETWithQuery("Action=DetachVDisk"
+                + "&vdiskId=CONTRACT-VSYS00001-D-0001"
+                + "&vserverId=CONTRACT-VSYS00001-S-0006"
+                + "&vsysId=CONTRACT-VSYS00001");
+        HttpResponse response = HttpResponse.builder().statusCode(200)
+                .payload(payloadFromResource("/DetachVDisk-response.xml"))
+                .build();
+
+        AdditionalDiskApi api = requestSendsResponse(request, response)
+                .getAdditionalDiskApi();
+
+        api.detach("CONTRACT-VSYS00001-D-0001", "CONTRACT-VSYS00001-S-0006");
+    }
+
+    public void testDestroyBackup() {
+        HttpRequest request = buildGETWithQuery("Action=DestroyVDiskBackup"
+                + "&vsysId=CONTRACT-VSYS00001"
+                + "&backupId=003");
+        HttpResponse response = HttpResponse.builder().statusCode(200)
+                .payload(payloadFromResource("/DestroyVDiskBackup-response.xml"))
+                .build();
+
+        AdditionalDiskApi api = requestSendsResponse(request, response)
+                .getAdditionalDiskApi();
+
+        api.destroyBackup("CONTRACT-VSYS00001", "003");
+    }
+
+}
diff --git a/labs/fgcp/src/test/java/org/jclouds/fujitsu/fgcp/services/BaseFGCPApiLiveTest.java b/labs/fgcp/src/test/java/org/jclouds/fujitsu/fgcp/services/BaseFGCPApiLiveTest.java
new file mode 100644
index 0000000..1da6e1f
--- /dev/null
+++ b/labs/fgcp/src/test/java/org/jclouds/fujitsu/fgcp/services/BaseFGCPApiLiveTest.java
@@ -0,0 +1,84 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.fujitsu.fgcp.services;
+
+import java.util.Properties;
+
+import org.jclouds.Constants;
+import org.jclouds.compute.internal.BaseComputeServiceContextLiveTest;
+import org.jclouds.fujitsu.fgcp.FGCPApi;
+import org.jclouds.fujitsu.fgcp.FGCPAsyncApi;
+import org.jclouds.rest.RestContext;
+import org.jclouds.sshj.config.SshjSshClientModule;
+import org.testng.annotations.BeforeGroups;
+
+import com.google.inject.Module;
+
+/**
+ * @author Dies Koper
+ */
+public class BaseFGCPApiLiveTest extends BaseComputeServiceContextLiveTest {
+
+    protected RestContext<FGCPApi, FGCPAsyncApi> fgcpContext;
+
+    public BaseFGCPApiLiveTest() {
+        provider = "fgcp";
+    }
+
+    @Override
+    protected Properties setupProperties() {
+        Properties overrides = super.setupProperties();
+
+        String proxy = System.getenv("http_proxy");
+        if (proxy != null) {
+
+            String[] parts = proxy.split("http://|:|@");
+
+            overrides.setProperty(Constants.PROPERTY_PROXY_HOST,
+                    parts[parts.length - 2]);
+            overrides.setProperty(Constants.PROPERTY_PROXY_PORT,
+                    parts[parts.length - 1]);
+
+            if (parts.length >= 4) {
+                overrides.setProperty(Constants.PROPERTY_PROXY_USER,
+                        parts[parts.length - 4]);
+                overrides.setProperty(Constants.PROPERTY_PROXY_PASSWORD,
+                        parts[parts.length - 3]);
+            }
+        }
+
+        // enables peer verification using the CAs bundled with the JRE (or
+        // value of javax.net.ssl.trustStore if set)
+        overrides.setProperty(Constants.PROPERTY_TRUST_ALL_CERTS, "false");
+
+        return overrides;
+    }
+
+    @BeforeGroups(groups = { "integration", "live" })
+    @Override
+    public void setupContext() {
+        super.setupContext();
+        fgcpContext = view.unwrap();
+    }
+
+    @Override
+    protected Module getSshModule() {
+        return new SshjSshClientModule();
+    }
+}
diff --git a/labs/fgcp/src/test/java/org/jclouds/fujitsu/fgcp/services/BaseFGCPRestApiExpectTest.java b/labs/fgcp/src/test/java/org/jclouds/fujitsu/fgcp/services/BaseFGCPRestApiExpectTest.java
new file mode 100644
index 0000000..2fb42da
--- /dev/null
+++ b/labs/fgcp/src/test/java/org/jclouds/fujitsu/fgcp/services/BaseFGCPRestApiExpectTest.java
@@ -0,0 +1,125 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.fujitsu.fgcp.services;
+
+import static org.testng.Assert.assertNotNull;
+
+import java.net.URI;
+import java.net.URL;
+import java.util.Calendar;
+import java.util.Locale;
+import java.util.TimeZone;
+
+import javax.ws.rs.core.MediaType;
+
+import org.jclouds.fujitsu.fgcp.FGCPApi;
+import org.jclouds.fujitsu.fgcp.FGCPProviderMetadata;
+import org.jclouds.fujitsu.fgcp.compute.FGCPRestClientModule;
+import org.jclouds.http.HttpRequest;
+import org.jclouds.io.Payload;
+import org.jclouds.providers.ProviderMetadata;
+import org.jclouds.rest.ConfiguresRestClient;
+import org.jclouds.rest.internal.BaseRestClientExpectTest;
+
+import com.google.common.collect.ImmutableMultimap;
+import com.google.inject.Module;
+
+/**
+ * @author Dies Koper
+ */
+public class BaseFGCPRestApiExpectTest extends
+		BaseRestClientExpectTest<FGCPApi> {
+
+    public BaseFGCPRestApiExpectTest() {
+		provider = "fgcp";
+
+        // self-signed dummy cert:
+        // keytool -genkey -alias test-fgcp -keyalg RSA -keysize 1024 -validity 5475 -dname "CN=localhost" -keystore jclouds-test-fgcp.p12 -storepass jcloudsjclouds -storetype pkcs12
+		String cert = "/certs/jclouds-test-fgcp.p12";
+		URL url = this.getClass().getResource(cert);
+		assertNotNull(url, cert + " not found");
+
+		identity = url.getFile();
+		credential = "jcloudsjclouds";
+	}
+
+	@ConfiguresRestClient
+	protected static final class TestFGCPRestClientModule extends
+			FGCPRestClientModule {
+
+		@Override
+		protected Calendar provideCalendar() {
+			// pick country/TZ with no DST just in case to maintain constant
+			// time wherever the tests are run.
+			Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("GMT-9"),
+					Locale.JAPAN);
+			cal.setTimeInMillis(1234567890);
+			return cal;
+		}
+	}
+
+	@Override
+	protected Module createModule() {
+		return new TestFGCPRestClientModule();
+	}
+
+    @Override
+    protected ProviderMetadata createProviderMetadata() {
+        return new FGCPProviderMetadata();
+    }
+
+    @Override
+    public Payload payloadFromResource(String resource) {
+        return super.payloadFromResource("/responses" + resource);
+    }
+
+    protected static HttpRequest buildGETWithQuery(String query) {
+        URI uri = URI.create("https://api.globalcloud.fujitsu.com.au/ovissapi/endpoint"
+                + "?Version=2012-02-18"
+                + "&" + query
+                + "&Locale=en"
+                + "&AccessKeyId=R01ULTA5OjAwJjEyMzQ1Njc4OTAmMS4wJlNIQTF3aXRoUlNB"
+//                + "&Signature=G2rGfLAkbq0IURQfXIWYxj3BnMGbjRk4KPnZLAze3Lt4SMMRt8lkjqKvR5Cm%2BnFpDN7J6IprVCCsIrRq5BqPeXT6xtWyb6qMNds2BAr1h%2FJePGs0UosOh2tgPUMSFlZwLVjgNyrSa2zeHA3AEHjF6H1jqcWXXqfCAD4SOHaNavk%3D");
+        + "&Signature=G2rGfLAkbq0IURQfXIWYxj3BnMGbjRk4KPnZLAze3Lt4SMMRt8lkjqKvR5Cm%2BnFpDN7J6IprVCCs%0D%0AIrRq5BqPeXT6xtWyb6qMNds2BAr1h%2FJePGs0UosOh2tgPUMSFlZwLVjgNyrSa2zeHA3AEHjF6H1j%0D%0AqcWXXqfCAD4SOHaNavk%3D");
+        return HttpRequest
+                .builder()
+                .method("GET")
+                .endpoint(uri)
+                .addHeader("Accept", "text/xml")
+                .addHeader("User-Agent", "OViSS-API-CLIENT")
+                .build();
+    }
+
+    protected HttpRequest preparePOSTForAction(String action) {
+        return HttpRequest
+                .builder()
+                .method("POST")
+                .endpoint(
+                        URI.create("https://api.globalcloud.fujitsu.com.au/ovissapi/endpoint"))
+                .payload(
+                        payloadFromResourceWithContentType(
+                                "/" + action.toLowerCase() + "-request.xml",
+                                MediaType.TEXT_XML))
+                .headers(
+                        ImmutableMultimap.<String, String> builder()
+                                .put("Accept", "text/xml")
+                                .put("User-Agent", "OViSS-API-CLIENT").build())
+                .build();
+    }
+}
diff --git a/labs/fgcp/src/test/java/org/jclouds/fujitsu/fgcp/services/BuiltinServerApiExpectTest.java b/labs/fgcp/src/test/java/org/jclouds/fujitsu/fgcp/services/BuiltinServerApiExpectTest.java
new file mode 100644
index 0000000..acb2f16
--- /dev/null
+++ b/labs/fgcp/src/test/java/org/jclouds/fujitsu/fgcp/services/BuiltinServerApiExpectTest.java
@@ -0,0 +1,215 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.fujitsu.fgcp.services;
+
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertEquals;
+
+import java.util.Set;
+
+import org.jclouds.fujitsu.fgcp.domain.BuiltinServer;
+import org.jclouds.fujitsu.fgcp.domain.BuiltinServerBackup;
+import org.jclouds.fujitsu.fgcp.domain.BuiltinServerStatus;
+import org.jclouds.http.HttpRequest;
+import org.jclouds.http.HttpResponse;
+import org.testng.annotations.Test;
+
+/**
+ * @author Dies Koper
+ */
+@Test(groups = "unit", testName = "BuiltinServerApiExpectTest", singleThreaded = true)
+public class BuiltinServerApiExpectTest extends BaseFGCPRestApiExpectTest {
+
+    public void testStart() {
+        HttpRequest request = buildGETWithQuery("Action=StartEFM"
+                + "&efmId=CONTRACT-VSYS00001-S-0001"
+                + "&vsysId=CONTRACT-VSYS00001");
+        HttpResponse response = HttpResponse.builder().statusCode(200)
+                .payload(payloadFromResource("/StartEFM-response.xml"))
+                .build();
+
+        BuiltinServerApi api = requestSendsResponse(request, response)
+                .getFirewallApi();
+
+        api.start("CONTRACT-VSYS00001-S-0001");
+    }
+
+    public void testStop() {
+        HttpRequest request = buildGETWithQuery("Action=StopEFM"
+                + "&efmId=CONTRACT-VSYS00001-S-0001"
+                + "&vsysId=CONTRACT-VSYS00001");
+        HttpResponse response = HttpResponse.builder().statusCode(200)
+                .payload(payloadFromResource("/StopEFM-response.xml"))
+                .build();
+
+        BuiltinServerApi api = requestSendsResponse(request, response)
+                .getFirewallApi();
+
+        api.stop("CONTRACT-VSYS00001-S-0001");
+    }
+
+    public void testDestroy() {
+        HttpRequest request = buildGETWithQuery("Action=DestroyEFM"
+                + "&efmId=CONTRACT-VSYS00001-S-0001"
+                + "&vsysId=CONTRACT-VSYS00001");
+        HttpResponse response = HttpResponse.builder().statusCode(200)
+                .payload(payloadFromResource("/DestroyEFM-response.xml"))
+                .build();
+
+        BuiltinServerApi api = requestSendsResponse(request, response)
+                .getFirewallApi();
+
+        api.destroy("CONTRACT-VSYS00001-S-0001");
+    }
+
+    public void testGet() {
+        HttpRequest request = buildGETWithQuery("Action=GetEFMAttributes"
+                + "&efmId=CONTRACT-VSYS00001-S-0001"
+                + "&vsysId=CONTRACT-VSYS00001");
+        HttpResponse response = HttpResponse
+                .builder()
+                .statusCode(200)
+                .payload(
+                        payloadFromResource("/GetEFMAttributes-response.xml"))
+                .build();
+
+        BuiltinServerApi api = requestSendsResponse(request, response)
+                .getFirewallApi();
+
+        assertEquals(api.get("CONTRACT-VSYS00001-S-0001").getType(), BuiltinServer.BuiltinServerType.FW);
+    }
+
+/*
+    public void testGetDetails() {
+        HttpRequest request = buildGETWithQuery("Action=GetEFMConfiguration"
+                + "&efmId=CONTRACT-VSYS00001-S-0001"
+                + "&vsysId=CONTRACT-VSYS00001");
+        HttpResponse response = HttpResponse
+                .builder()
+                .statusCode(200)
+                .payload(
+                        payloadFromResource("/GetEFMConfiguration-response.xml"))
+                .build();
+
+        BuiltinServerApi api = requestSendsResponse(request, response)
+                .getFirewallApi();
+
+//        assertNotNull(api.getDetails("CONTRACT-VSYS00001-S-0001"));
+    }
+*/
+
+    public void testGetStatus() {
+        HttpRequest request = buildGETWithQuery("Action=GetEFMStatus"
+                + "&efmId=CONTRACT-VSYS00001-S-0001"
+                + "&vsysId=CONTRACT-VSYS00001");
+        HttpResponse response = HttpResponse
+                .builder()
+                .statusCode(200)
+                .payload(
+                        payloadFromResource("/GetEFMStatus-response.xml"))
+                .build();
+
+        BuiltinServerApi api = requestSendsResponse(request, response)
+                .getFirewallApi();
+
+        assertEquals(api.getStatus("CONTRACT-VSYS00001-S-0001"), BuiltinServerStatus.RUNNING);
+    }
+
+    public void testUpdate() {
+        HttpRequest request = buildGETWithQuery("Action=UpdateEFMAttribute"
+                + "&efmId=CONTRACT-VSYS00001-S-0001"
+                + "&attributeValue=new%20name"
+                + "&attributeName=vserverName"
+                + "&vsysId=CONTRACT-VSYS00001");
+        HttpResponse response = HttpResponse
+                .builder()
+                .statusCode(200)
+                .payload(
+                        payloadFromResource("/UpdateEFMAttribute-response.xml"))
+                .build();
+
+        BuiltinServerApi api = requestSendsResponse(request, response)
+                .getFirewallApi();
+
+        api.update("CONTRACT-VSYS00001-S-0001", "vserverName", "new name");
+    }
+
+    public void testBackup() {
+        HttpRequest request = buildGETWithQuery("Action=BackupEFM"
+                + "&efmId=CONTRACT-VSYS00001-S-0001"
+                + "&vsysId=CONTRACT-VSYS00001");
+        HttpResponse response = HttpResponse.builder().statusCode(200)
+                .payload(payloadFromResource("/BackupEFM-response.xml"))
+                .build();
+
+        BuiltinServerApi api = requestSendsResponse(request, response)
+                .getFirewallApi();
+
+        api.backup("CONTRACT-VSYS00001-S-0001");
+    }
+
+    public void testRestore() {
+        HttpRequest request = buildGETWithQuery("Action=RestoreEFM"
+                + "&efmId=CONTRACT-VSYS00001-S-0001"
+                + "&backupId=003"
+                + "&vsysId=CONTRACT-VSYS00001");
+        HttpResponse response = HttpResponse.builder().statusCode(200)
+                .payload(payloadFromResource("/RestoreEFM-response.xml"))
+                .build();
+
+        BuiltinServerApi api = requestSendsResponse(request, response)
+                .getFirewallApi();
+
+        api.restore("CONTRACT-VSYS00001-S-0001", "003");
+    }
+
+    public void testListBackups() {
+        HttpRequest request = buildGETWithQuery("Action=ListEFMBackup"
+                + "&efmId=CONTRACT-VSYS00001-S-0001"
+                + "&vsysId=CONTRACT-VSYS00001");
+        HttpResponse response = HttpResponse.builder().statusCode(200)
+                .payload(payloadFromResource("/ListEFMBackup-response.xml"))
+                .build();
+
+        BuiltinServerApi api = requestSendsResponse(request, response)
+                .getFirewallApi();
+
+        Set<BuiltinServerBackup> backups = api.listBackups("CONTRACT-VSYS00001-S-0001");
+        assertNotNull(backups, "backups");
+        assertEquals(backups.size(), 2);
+        assertEquals(backups.iterator().next().getId(), "001");
+        assertEquals(backups.iterator().next().getTime(), "20121008201127");
+    }
+
+    public void testDestroyBackup() {
+        HttpRequest request = buildGETWithQuery("Action=DestroyEFMBackup"
+                + "&efmId=CONTRACT-VSYS00001-S-0001"
+                + "&backupId=003"
+                + "&vsysId=CONTRACT-VSYS00001");
+        HttpResponse response = HttpResponse.builder().statusCode(200)
+                .payload(payloadFromResource("/DestroyEFMBackup-response.xml"))
+                .build();
+
+        BuiltinServerApi api = requestSendsResponse(request, response)
+                .getFirewallApi();
+
+        api.destroyBackup("CONTRACT-VSYS00001-S-0001", "003");
+    }
+
+}
diff --git a/labs/fgcp/src/test/java/org/jclouds/fujitsu/fgcp/services/DiskImageApiExpectTest.java b/labs/fgcp/src/test/java/org/jclouds/fujitsu/fgcp/services/DiskImageApiExpectTest.java
new file mode 100644
index 0000000..d0ae9a0
--- /dev/null
+++ b/labs/fgcp/src/test/java/org/jclouds/fujitsu/fgcp/services/DiskImageApiExpectTest.java
@@ -0,0 +1,79 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.fujitsu.fgcp.services;
+
+import static org.testng.Assert.assertEquals;
+
+import org.jclouds.fujitsu.fgcp.domain.DiskImage;
+import org.jclouds.http.HttpRequest;
+import org.jclouds.http.HttpResponse;
+import org.testng.annotations.Test;
+
+/**
+ * @author Dies Koper
+ */
+@Test(groups = "unit", testName = "DiskImageApiExpectTest", singleThreaded = true)
+public class DiskImageApiExpectTest extends BaseFGCPRestApiExpectTest {
+
+    public void testGet() {
+        HttpRequest request = buildGETWithQuery("Action=GetDiskImageAttributes"
+                + "&diskImageId=IMG_A1B2C3_1234567890ABCD");
+        HttpResponse response = HttpResponse.builder().statusCode(200)
+                .payload(payloadFromResource("/GetDiskImageAttributes-response.xml"))
+                .build();
+
+        DiskImageApi api = requestSendsResponse(request, response)
+                .getDiskImageApi();
+
+        DiskImage image = api.get("IMG_A1B2C3_1234567890ABCD");
+
+        assertEquals(image.getId(), "IMG_A1B2C3_1234567890ABCD");
+        assertEquals(image.getCreatorName(), "ABCDEFGH");
+    }
+
+    public void testUpdate() {
+        HttpRequest request = buildGETWithQuery("Action=UpdateDiskImageAttribute"
+                + "&diskImageId=IMG_A1B2C3_1234567890ABCD"
+                + "&attributeName=updateName"
+                + "&updateLcId=en"
+                + "&attributeValue=new-name");
+        HttpResponse response = HttpResponse.builder().statusCode(200)
+                .payload(payloadFromResource("/UpdateDiskImageAttribute-response.xml"))
+                .build();
+
+        DiskImageApi api = requestSendsResponse(request, response)
+                .getDiskImageApi();
+
+        api.update("IMG_A1B2C3_1234567890ABCD", "en", "updateName", "new-name");
+    }
+
+    public void testDeregister() {
+        HttpRequest request = buildGETWithQuery("Action=UnregisterDiskImage"
+                + "&diskImageId=IMG_A1B2C3_1234567890ABCD");
+        HttpResponse response = HttpResponse.builder().statusCode(200)
+                .payload(payloadFromResource("/UnregisterDiskImage-response.xml"))
+                .build();
+
+        DiskImageApi api = requestSendsResponse(request, response)
+                .getDiskImageApi();
+
+        api.deregister("IMG_A1B2C3_1234567890ABCD");
+    }
+
+}
diff --git a/labs/fgcp/src/test/java/org/jclouds/fujitsu/fgcp/services/PublicIPAddressApiExpectTest.java b/labs/fgcp/src/test/java/org/jclouds/fujitsu/fgcp/services/PublicIPAddressApiExpectTest.java
new file mode 100644
index 0000000..226ec07
--- /dev/null
+++ b/labs/fgcp/src/test/java/org/jclouds/fujitsu/fgcp/services/PublicIPAddressApiExpectTest.java
@@ -0,0 +1,109 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.fujitsu.fgcp.services;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
+
+import org.jclouds.fujitsu.fgcp.domain.PublicIP;
+import org.jclouds.fujitsu.fgcp.domain.PublicIPStatus;
+import org.jclouds.http.HttpRequest;
+import org.jclouds.http.HttpResponse;
+import org.testng.annotations.Test;
+
+/**
+ * @author Dies Koper
+ */
+@Test(groups = "unit", testName = "PublicIPAddressApiExpectTest", singleThreaded = true)
+public class PublicIPAddressApiExpectTest extends BaseFGCPRestApiExpectTest {
+
+    public void testAttach() {
+        HttpRequest request = buildGETWithQuery("Action=AttachPublicIP"
+                + "&vsysId=CONTRACT-VSYS00001"
+                + "&publicIp=123.45.67.89");
+        HttpResponse response = HttpResponse.builder().statusCode(200)
+                .payload(payloadFromResource("/AttachPublicIP-response.xml"))
+                .build();
+
+        PublicIPAddressApi api = requestSendsResponse(request, response)
+                .getPublicIPAddressApi();
+
+        api.attach("CONTRACT-VSYS00001", "123.45.67.89");
+    }
+
+    public void testDetach() {
+        HttpRequest request = buildGETWithQuery("Action=DetachPublicIP"
+                + "&vsysId=CONTRACT-VSYS00001"
+                + "&publicIp=123.45.67.89");
+        HttpResponse response = HttpResponse.builder().statusCode(200)
+                .payload(payloadFromResource("/DetachPublicIP-response.xml"))
+                .build();
+
+        PublicIPAddressApi api = requestSendsResponse(request, response)
+                .getPublicIPAddressApi();
+
+        api.detach("CONTRACT-VSYS00001", "123.45.67.89");
+    }
+
+    public void testFree() {
+        HttpRequest request = buildGETWithQuery("Action=FreePublicIP"
+                + "&vsysId=CONTRACT-VSYS00001"
+                + "&publicIp=123.45.67.89");
+        HttpResponse response = HttpResponse.builder().statusCode(200)
+                .payload(payloadFromResource("/FreePublicIP-response.xml"))
+                .build();
+
+        PublicIPAddressApi api = requestSendsResponse(request, response)
+                .getPublicIPAddressApi();
+
+        api.free("CONTRACT-VSYS00001", "123.45.67.89");
+    }
+
+    public void testGetStatus() {
+        HttpRequest request = buildGETWithQuery("Action=GetPublicIPStatus"
+                + "&publicIp=123.45.67.89");
+        HttpResponse response = HttpResponse.builder().statusCode(200)
+                .payload(payloadFromResource("/GetPublicIPStatus-response.xml"))
+                .build();
+
+        PublicIPAddressApi api = requestSendsResponse(request, response)
+                .getPublicIPAddressApi();
+
+        PublicIPStatus status = api.getStatus("123.45.67.89");
+        assertEquals(status, PublicIPStatus.ATTACHED);
+    }
+
+    public void testGet() {
+        HttpRequest request = buildGETWithQuery("Action=GetPublicIPAttributes"
+                + "&publicIp=123.45.67.89");
+        HttpResponse response = HttpResponse.builder().statusCode(200)
+                .payload(payloadFromResource("/GetPublicIPAttributes-response.xml"))
+                .build();
+
+        PublicIPAddressApi api = requestSendsResponse(request, response)
+                .getPublicIPAddressApi();
+
+        PublicIP ip = api.get("123.45.67.89");
+
+        assertNotNull(ip, "ip");
+        assertEquals(ip.getAddress(), "123.45.67.89");
+        assertEquals(ip.getVersion(), PublicIP.Version.IPv4);
+    }
+
+}
diff --git a/labs/fgcp/src/test/java/org/jclouds/fujitsu/fgcp/services/SystemTemplateApiExpectTest.java b/labs/fgcp/src/test/java/org/jclouds/fujitsu/fgcp/services/SystemTemplateApiExpectTest.java
new file mode 100644
index 0000000..182c13f
--- /dev/null
+++ b/labs/fgcp/src/test/java/org/jclouds/fujitsu/fgcp/services/SystemTemplateApiExpectTest.java
@@ -0,0 +1,103 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.fujitsu.fgcp.services;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
+
+import org.jclouds.fujitsu.fgcp.domain.VSystem;
+import org.jclouds.fujitsu.fgcp.domain.VSystemDescriptor;
+import org.jclouds.http.HttpRequest;
+import org.jclouds.http.HttpResponse;
+import org.testng.annotations.Test;
+
+/**
+ * @author Dies Koper
+ */
+@Test(groups = "unit", testName = "SystemTemplateApiExpectTest", singleThreaded = true)
+public class SystemTemplateApiExpectTest extends BaseFGCPRestApiExpectTest {
+
+    public void testGet() {
+        HttpRequest request = buildGETWithQuery("Action=GetVSYSDescriptorConfiguration"
+                + "&vsysDescriptorId=3-tier%20Skeleton");
+        HttpResponse response = HttpResponse
+                .builder()
+                .statusCode(200)
+                .payload(
+                        payloadFromResource("/GetVSYSDescriptorConfiguration-response.xml"))
+                .build();
+        SystemTemplateApi client = requestSendsResponse(request, response)
+                .getSystemTemplateApi();
+
+        VSystemDescriptor desc = client.get("3-tier Skeleton");
+        assertNotNull(desc, "desc");
+//        assertEquals(desc.)
+    }
+
+
+    public void testUpdate() {
+        HttpRequest request = buildGETWithQuery("Action=UpdateVSYSDescriptorAttribute"
+                + "&vsysDescriptorId=3-tier%20Skeleton" + "&attributeName=updateName"
+                + "&updateLcId=en"
+                + "&attributeValue=new-name");
+        HttpResponse response = HttpResponse
+                .builder()
+                .statusCode(200)
+                .payload(
+                        payloadFromResource("/UpdateVSYSDescriptorAttribute-response.xml"))
+                .build();
+
+        SystemTemplateApi api = requestSendsResponse(request, response)
+                .getSystemTemplateApi();
+
+        api.update("3-tier Skeleton", "en", "updateName", "new-name");
+    }
+
+    public void testDeregister() {
+        HttpRequest request = buildGETWithQuery("Action=UnregisterVSYSDescriptor"
+                + "&vsysDescriptorId=3-tier%20Skeleton");
+        HttpResponse response = HttpResponse
+                .builder()
+                .statusCode(200)
+                .payload(
+                        payloadFromResource("/UnregisterVSYSDescriptor-response.xml"))
+                .build();
+
+        SystemTemplateApi api = requestSendsResponse(request, response)
+                .getSystemTemplateApi();
+
+        api.deregister("3-tier Skeleton");
+    }
+
+    public void testDeregisterPrivateTemplate() {
+        HttpRequest request = buildGETWithQuery("Action=UnregisterPrivateVSYSDescriptor"
+                + "&vsysDescriptorId=3-tier%20Skeleton");
+        HttpResponse response = HttpResponse
+                .builder()
+                .statusCode(200)
+                .payload(
+                        payloadFromResource("/UnregisterPrivateVSYSDescriptor-response.xml"))
+                .build();
+
+        SystemTemplateApi api = requestSendsResponse(request, response)
+                .getSystemTemplateApi();
+
+        api.deregisterPrivateTemplate("3-tier Skeleton");
+    }
+}
diff --git a/labs/fgcp/src/test/java/org/jclouds/fujitsu/fgcp/services/VirtualDCApiExpectTest.java b/labs/fgcp/src/test/java/org/jclouds/fujitsu/fgcp/services/VirtualDCApiExpectTest.java
new file mode 100644
index 0000000..277a449
--- /dev/null
+++ b/labs/fgcp/src/test/java/org/jclouds/fujitsu/fgcp/services/VirtualDCApiExpectTest.java
@@ -0,0 +1,207 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.fujitsu.fgcp.services;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertTrue;
+
+import java.util.Map;
+import java.util.Set;
+
+import org.jclouds.fujitsu.fgcp.domain.AddressRange;
+import org.jclouds.fujitsu.fgcp.domain.DiskImage;
+import org.jclouds.fujitsu.fgcp.domain.EventLog;
+import org.jclouds.fujitsu.fgcp.domain.PublicIP;
+import org.jclouds.fujitsu.fgcp.domain.ServerType;
+import org.jclouds.fujitsu.fgcp.domain.VSystem;
+import org.jclouds.http.HttpRequest;
+import org.jclouds.http.HttpResponse;
+import org.testng.annotations.Test;
+
+/**
+ * @author Dies Koper
+ */
+@Test(groups = "unit", testName = "VirtualDCApiExpectTest", singleThreaded = true)
+public class VirtualDCApiExpectTest extends BaseFGCPRestApiExpectTest {
+
+    public void testListVirtualSystems() {
+        HttpRequest request = buildGETWithQuery("Action=ListVSYS");
+        HttpResponse response = HttpResponse.builder()
+                .statusCode(200)
+                .payload(payloadFromResource("/ListVSYS-response.xml"))
+                .build();
+
+        VirtualDCApi api = requestSendsResponse(request, response).getVirtualDCApi();
+
+        Set<VSystem> vsysSet = api.listVirtualSystems();
+        assertEquals(vsysSet.size(), 2);
+    }
+
+    public void testCreateVirtualSystem() {
+        HttpRequest request = buildGETWithQuery("Action=CreateVSYS&vsysDescriptorId=myDescId&vsysName=myVSYS");
+        HttpResponse response = HttpResponse.builder()
+                .statusCode(200)
+                .payload(payloadFromResource("/CreateVSYS-response.xml"))
+                .build();
+        VirtualDCApi api = requestSendsResponse(request, response)
+                .getVirtualDCApi();
+
+        String vsysId = api.createVirtualSystem("myDescId", "myVSYS");
+        assertEquals(vsysId, "CONTRACT-VSYS00001", "vsysId: " + vsysId);
+    }
+
+
+    public void testListServerTypes() {
+        HttpRequest request = buildGETWithQuery("Action=ListServerType&diskImageId=dummy");
+        HttpResponse response = HttpResponse.builder()
+                .statusCode(200)
+                .payload(payloadFromResource("/ListServerType-response.xml"))
+                .build();
+        VirtualDCApi api = requestSendsResponse(request, response)
+                .getVirtualDCApi();
+
+        Set<ServerType> serverTypes = api.listServerTypes();
+        assertNotNull(serverTypes, "serverTypes");
+        assertEquals(serverTypes.size(), 4,
+                "Unexpected number of server types: " + serverTypes.size());
+    }
+
+    public void testListPublicIPs() {
+        HttpRequest request = buildGETWithQuery("Action=ListPublicIP");
+        HttpResponse response = HttpResponse.builder()
+                .statusCode(200)
+                .payload(payloadFromResource("/ListPublicIP-response.xml"))
+                .build();
+        VirtualDCApi api = requestSendsResponse(request, response)
+                .getVirtualDCApi();
+
+        Map<PublicIP, String> ips = api.listPublicIPs();
+
+        assertNotNull(ips, "ips");
+        assertEquals(ips.size(), 2, "Unexpected number of ips: " + ips.size());
+        assertEquals(ips.keySet().size(), 2, "Unexpected number of ips: " + ips.size());
+        assertTrue(ips.containsValue("ABCDEFGH-A123B456CE"), "missing system id");
+        assertEquals(ips.keySet().iterator().next().getVersion(), PublicIP.Version.IPv4);
+    }
+
+    public void testListDiskImages() {
+        HttpRequest request = buildGETWithQuery("Action=ListDiskImage");
+        HttpResponse response = HttpResponse.builder()
+                .statusCode(200)
+                .payload(payloadFromResource("/ListDiskImages-response.xml"))
+                .build();
+        VirtualDCApi api = requestSendsResponse(request, response)
+                .getVirtualDCApi();
+
+        Set<DiskImage> images = api.listDiskImages();
+
+        assertNotNull(images, "images");
+        assertTrue(images.size() > 5, "Unexpected number of images: " + images.size());
+    }
+
+    public void testListDiskImage() {
+        HttpRequest request = buildGETWithQuery("Action=ListDiskImage&vsysDescriptorId=IMG_A1B2C3_1234567890ABCD");
+        HttpResponse response = HttpResponse.builder()
+                .statusCode(200)
+                .payload(payloadFromResource("/ListDiskImage-response.xml"))
+                .build();
+        VirtualDCApi api = requestSendsResponse(request, response)
+                .getVirtualDCApi();
+
+        Set<DiskImage> images = api.listDiskImages(null, "IMG_A1B2C3_1234567890ABCD");
+
+        assertNotNull(images, "images");
+        assertTrue(images.size() == 1, "Unexpected number of images: " + images.size());
+    }
+
+    public void testGetAddressRange() {
+        HttpRequest request = buildGETWithQuery("Action=GetAddressRange");
+        HttpResponse response = HttpResponse.builder()
+                .statusCode(200)
+                .payload(payloadFromResource("/GetAddressRange-response.xml"))
+                .build();
+        VirtualDCApi api = requestSendsResponse(request, response)
+                .getVirtualDCApi();
+
+        Set<AddressRange> range = api.getAddressRange();
+        assertNotNull(range);
+        assertEquals(range.size(), 1);
+    }
+
+    public void testAddAddressRange() {
+        HttpRequest request = buildGETWithQuery("Action=AddAddressRange"
+                + "&pipFrom=192.168.0.0"
+                + "&pipTo=192.168.30.0");
+        HttpResponse response = HttpResponse.builder()
+                .statusCode(200)
+                .payload(payloadFromResource("/AddAddressRange-response.xml"))
+                .build();
+        VirtualDCApi api = requestSendsResponse(request, response)
+                .getVirtualDCApi();
+
+        api.addAddressRange("192.168.0.0", "192.168.30.0");
+    }
+
+    public void testDeleteAddressRange() {
+        HttpRequest request = buildGETWithQuery("Action=DeleteAddressRange"
+                + "&pipFrom=192.168.0.0"
+                + "&pipTo=192.168.30.0");
+        HttpResponse response = HttpResponse.builder()
+                .statusCode(200)
+                .payload(payloadFromResource("/DeleteAddressRange-response.xml"))
+                .build();
+        VirtualDCApi api = requestSendsResponse(request, response)
+                .getVirtualDCApi();
+
+        api.deleteAddressRange("192.168.0.0", "192.168.30.0");
+    }
+
+    public void testCreateAddressPool() {
+        HttpRequest request = buildGETWithQuery("Action=CreateAddressPool"
+                + "&pipFrom=192.168.0.0"
+                + "&pipTo=192.168.30.0");
+        HttpResponse response = HttpResponse.builder()
+                .statusCode(200)
+                .payload(payloadFromResource("/CreateAddressPool-response.xml"))
+                .build();
+        VirtualDCApi api = requestSendsResponse(request, response)
+                .getVirtualDCApi();
+
+        api.createAddressPool("192.168.0.0", "192.168.30.0");
+    }
+
+    public void testGetEventLog() {
+        HttpRequest request = buildGETWithQuery("Action=GetEventLog");
+        HttpResponse response = HttpResponse.builder()
+                .statusCode(200)
+                .payload(payloadFromResource("/GetEventLog-response.xml"))
+                .build();
+        VirtualDCApi api = requestSendsResponse(request, response)
+                .getVirtualDCApi();
+
+        Set<EventLog> logs = api.getEventLogs();
+        assertNotNull(logs);
+        //TODO: get one with several
+//        assertEquals(logs.size(), 1);
+    }
+
+
+
+}
diff --git a/labs/fgcp/src/test/java/org/jclouds/fujitsu/fgcp/services/VirtualDCApiLiveTest.java b/labs/fgcp/src/test/java/org/jclouds/fujitsu/fgcp/services/VirtualDCApiLiveTest.java
new file mode 100644
index 0000000..0e873ed
--- /dev/null
+++ b/labs/fgcp/src/test/java/org/jclouds/fujitsu/fgcp/services/VirtualDCApiLiveTest.java
@@ -0,0 +1,77 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.fujitsu.fgcp.services;
+
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertTrue;
+
+import java.util.Set;
+
+import org.jclouds.fujitsu.fgcp.domain.ServerType;
+import org.jclouds.fujitsu.fgcp.domain.VSystem;
+import org.testng.annotations.BeforeGroups;
+import org.testng.annotations.Test;
+
+/**
+ * @author Dies Koper
+ */
+@Test(groups = "live", enabled = true, singleThreaded = true, testName = "VirtualDCApiLiveTest")
+public class VirtualDCApiLiveTest extends BaseFGCPApiLiveTest {
+
+    private VirtualDCApi api;
+
+    @BeforeGroups(groups = { "live" })
+    public void setupContext() {
+        super.setupContext();
+        api = fgcpContext.getApi().getVirtualDCApi();
+    }
+
+    public void testListVirtualSystems() {
+/*        Properties overrides = setupProperties();
+        RestContext<FGCPClient, FGCPAsyncClientTest> context = new RestContextFactory().createContext(provider, ImmutableSet.<Module> of(new Log4JLoggingModule()),
+                overrides);*/
+
+        Set<VSystem> vsysSet = api.listVirtualSystems();
+        assertNotNull(vsysSet, "vsysSet");
+        assertTrue(vsysSet.size() > 0, "vsysSet.size() should be greater than 0");
+        for (VSystem vsys : vsysSet) {
+            System.out.println(vsys);
+        }
+    }
+
+/*    public void testCreateVirtualSystem() {
+        String vsysId = api.createVirtualSystem("abc", "def");
+
+        assertNotNull(vsysId, "vsysId");
+        assertFalse(vsysId.equals(""), "vsysId is empty (\"\")");
+        System.out.println("vsysId: " + vsysId);
+    }*/
+
+    public void testListServerTypes() {
+        Set<ServerType> serverTypes = api.listServerTypes();
+
+        assertNotNull(serverTypes, "serverTypes");
+        assertTrue(serverTypes.size() == 4, "serverTypes.size should return 4, not " + serverTypes.size());
+
+//        System.out.println("listServerTypes: " + serverTypes);
+    }
+
+
+
+}
diff --git a/labs/fgcp/src/test/java/org/jclouds/fujitsu/fgcp/services/VirtualServerApiExpectTest.java b/labs/fgcp/src/test/java/org/jclouds/fujitsu/fgcp/services/VirtualServerApiExpectTest.java
new file mode 100644
index 0000000..198993c
--- /dev/null
+++ b/labs/fgcp/src/test/java/org/jclouds/fujitsu/fgcp/services/VirtualServerApiExpectTest.java
@@ -0,0 +1,221 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.fujitsu.fgcp.services;
+
+import static org.testng.AssertJUnit.assertNotNull;
+import static org.testng.Assert.assertEquals;
+
+import org.jclouds.fujitsu.fgcp.domain.VServerStatus;
+import org.jclouds.fujitsu.fgcp.domain.VServerWithDetails;
+import org.jclouds.http.HttpRequest;
+import org.jclouds.http.HttpResponse;
+import org.testng.annotations.Test;
+
+/**
+ * @author Dies Koper
+ */
+@Test(groups = "unit", testName = "VirtualServerApiExpectTest", singleThreaded = true)
+public class VirtualServerApiExpectTest extends BaseFGCPRestApiExpectTest {
+
+    public void testStart() {
+        HttpRequest request = buildGETWithQuery("Action=StartVServer"
+                + "&vserverId=CONTRACT-VSYS00001-S-0005"
+                + "&vsysId=CONTRACT-VSYS00001");
+        HttpResponse response = HttpResponse.builder().statusCode(200)
+                .payload(payloadFromResource("/StartVServer-response.xml"))
+                .build();
+
+        VirtualServerApi api = requestSendsResponse(request, response)
+                .getVirtualServerApi();
+
+        api.start("CONTRACT-VSYS00001-S-0005");
+    }
+
+    public void testStop() {
+        HttpRequest request = buildGETWithQuery("Action=StopVServer"
+                + "&vserverId=CONTRACT-VSYS00001-S-0005"
+                + "&vsysId=CONTRACT-VSYS00001");
+        HttpResponse response = HttpResponse.builder().statusCode(200)
+                .payload(payloadFromResource("/StopVServer-response.xml"))
+                .build();
+
+        VirtualServerApi api = requestSendsResponse(request, response)
+                .getVirtualServerApi();
+
+        api.stop("CONTRACT-VSYS00001-S-0005");
+    }
+
+    public void testStopForcefully() {
+        HttpRequest request = buildGETWithQuery("Action=StopVServer"
+                + "&force=true"
+                + "&vserverId=CONTRACT-VSYS00001-S-0005"
+                + "&vsysId=CONTRACT-VSYS00001");
+        HttpResponse response = HttpResponse.builder().statusCode(200)
+                .payload(payloadFromResource("/StopVServer-response.xml"))
+                .build();
+
+        VirtualServerApi api = requestSendsResponse(request, response)
+                .getVirtualServerApi();
+
+        api.stopForcefully("CONTRACT-VSYS00001-S-0005");
+    }
+
+    public void testDestroy() {
+        HttpRequest request = buildGETWithQuery("Action=DestroyVServer"
+                + "&vserverId=CONTRACT-VSYS00001-S-0005"
+                + "&vsysId=CONTRACT-VSYS00001");
+        HttpResponse response = HttpResponse.builder().statusCode(200)
+                .payload(payloadFromResource("/DestroyVServer-response.xml"))
+                .build();
+
+        VirtualServerApi api = requestSendsResponse(request, response)
+                .getVirtualServerApi();
+
+        api.destroy("CONTRACT-VSYS00001-S-0005");
+    }
+
+    public void testGet() {
+        HttpRequest request = buildGETWithQuery("Action=GetVServerAttributes"
+                + "&vserverId=CONTRACT-VSYS00001-S-0005"
+                + "&vsysId=CONTRACT-VSYS00001");
+        HttpResponse response = HttpResponse
+                .builder()
+                .statusCode(200)
+                .payload(
+                        payloadFromResource("/GetVServerAttributes-response.xml"))
+                .build();
+
+        VirtualServerApi api = requestSendsResponse(request, response)
+                .getVirtualServerApi();
+
+        assertNotNull(api.get("CONTRACT-VSYS00001-S-0005"));
+    }
+
+    public void testGetDetails() {
+        HttpRequest request = buildGETWithQuery("Action=GetVServerConfiguration"
+                + "&vserverId=CONTRACT-VSYS00001-S-0005"
+                + "&vsysId=CONTRACT-VSYS00001");
+        HttpResponse response = HttpResponse
+                .builder()
+                .statusCode(200)
+                .payload(
+                        payloadFromResource("/GetVServerConfiguration-response.xml"))
+                .build();
+
+        VirtualServerApi api = requestSendsResponse(request, response)
+                .getVirtualServerApi();
+
+        VServerWithDetails server = api.getDetails("CONTRACT-VSYS00001-S-0005");
+        assertNotNull(server);
+        assertEquals(server.getId(), "CONTRACT-VSYS00001-S-0005");
+        assertEquals(server.getVnics().iterator().next().getNicNo(), 0);
+        assertEquals(server.getVnics().iterator().next().getPrivateIp(), "192.168.4.13");
+        assertEquals(server.getVnics().iterator().next().getNetworkId(), "CONTRACT-VSYS00001-N-DMZ");
+        assertEquals(server.getImage().getId(), "IMG_A1B2C3_1234567890ABCD");
+        assertEquals(server.getImage().getSysvolSize(), 10.0f);
+    }
+
+    public void testGetStatus() {
+        HttpRequest request = buildGETWithQuery("Action=GetVServerStatus"
+                + "&vserverId=CONTRACT-VSYS00001-S-0005"
+                + "&vsysId=CONTRACT-VSYS00001");
+        HttpResponse response = HttpResponse
+                .builder()
+                .statusCode(200)
+                .payload(
+                        payloadFromResource("/GetVServerStatus-response.xml"))
+                .build();
+
+        VirtualServerApi api = requestSendsResponse(request, response)
+                .getVirtualServerApi();
+
+        assertEquals(api.getStatus("CONTRACT-VSYS00001-S-0005"), VServerStatus.STOPPED);
+    }
+
+    public void testInitialPassword() {
+        HttpRequest request = buildGETWithQuery("Action=GetVServerInitialPassword"
+                + "&vserverId=CONTRACT-VSYS00001-S-0005"
+                + "&vsysId=CONTRACT-VSYS00001");
+        HttpResponse response = HttpResponse
+                .builder()
+                .statusCode(200)
+                .payload(
+                        payloadFromResource("/GetVServerInitialPassword-response.xml"))
+                .build();
+
+        VirtualServerApi api = requestSendsResponse(request, response)
+                .getVirtualServerApi();
+
+        assertEquals(api.getInitialPassword("CONTRACT-VSYS00001-S-0005"), "mySecretpwd1");
+    }
+
+    public void testUpdate() {
+        HttpRequest request = buildGETWithQuery("Action=UpdateVServerAttribute"
+                + "&vserverId=CONTRACT-VSYS00001-S-0005"
+                + "&attributeValue=new%20name"
+                + "&attributeName=vserverName"
+                + "&vsysId=CONTRACT-VSYS00001");
+        HttpResponse response = HttpResponse
+                .builder()
+                .statusCode(200)
+                .payload(
+                        payloadFromResource("/UpdateVServerAttribute-response.xml"))
+                .build();
+
+        VirtualServerApi api = requestSendsResponse(request, response)
+                .getVirtualServerApi();
+
+        api.update("CONTRACT-VSYS00001-S-0005", "vserverName", "new name");
+    }
+
+    public void testAttachDisk() {
+        HttpRequest request = buildGETWithQuery("Action=AttachVDisk"
+                + "&vserverId=CONTRACT-VSYS00001-S-0005"
+                + "&vdiskId=CONTRACT-VSYS00001-D-0001"
+                + "&vsysId=CONTRACT-VSYS00001");
+        HttpResponse response = HttpResponse.builder().statusCode(200)
+                .payload(payloadFromResource("/AttachVDisk-response.xml"))
+                .build();
+
+        VirtualServerApi api = requestSendsResponse(request, response)
+                .getVirtualServerApi();
+
+        api.attachDisk("CONTRACT-VSYS00001-S-0005", "CONTRACT-VSYS00001-D-0001");
+    }
+
+/*    public void testGetPerformanceInformation() {
+        HttpRequest request = buildGETWithQuery("Action=GetPerformanceInformation"
+                + "&serverId=CONTRACT-VSYS00001-S-0005"
+                + "&interval=10minute"
+                + "&vsysId=CONTRACT-VSYS00001");
+        HttpResponse response = HttpResponse
+                .builder()
+                .statusCode(200)
+                .payload(
+                        payloadFromResource("/GetPerformanceInformation-response.xml"))
+                .build();
+
+        VirtualServerApi api = requestSendsResponse(request, response)
+                .getVirtualServerApi();
+
+        assertNotNull(api.getPerformanceInformation(
+                "CONTRACT-VSYS00001-S-0005", "10minute"));
+    }
+*/
+}
diff --git a/labs/fgcp/src/test/java/org/jclouds/fujitsu/fgcp/services/VirtualSystemApiExpectTest.java b/labs/fgcp/src/test/java/org/jclouds/fujitsu/fgcp/services/VirtualSystemApiExpectTest.java
new file mode 100644
index 0000000..31aaed1
--- /dev/null
+++ b/labs/fgcp/src/test/java/org/jclouds/fujitsu/fgcp/services/VirtualSystemApiExpectTest.java
@@ -0,0 +1,259 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.fujitsu.fgcp.services;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertTrue;
+
+import java.util.Set;
+
+import org.jclouds.fujitsu.fgcp.domain.BuiltinServer;
+import org.jclouds.fujitsu.fgcp.domain.PublicIP;
+import org.jclouds.fujitsu.fgcp.domain.VDisk;
+import org.jclouds.fujitsu.fgcp.domain.VServer;
+import org.jclouds.fujitsu.fgcp.domain.VSystem;
+import org.jclouds.fujitsu.fgcp.domain.VSystemStatus;
+import org.jclouds.http.HttpRequest;
+import org.jclouds.http.HttpResponse;
+import org.testng.annotations.Test;
+
+/**
+ * @author Dies Koper
+ */
+@Test(groups = "unit", testName = "VirtualSystemApiExpectTest", singleThreaded = true)
+public class VirtualSystemApiExpectTest extends BaseFGCPRestApiExpectTest {
+
+    public void testGet() {
+        HttpRequest request = buildGETWithQuery("Action=GetVSYSAttributes&vsysId=ABCDEFGH-A123B456CE");
+        HttpResponse response = HttpResponse
+                .builder()
+                .statusCode(200)
+                .payload(
+                        payloadFromResource("/GetVSYSAttributes-response.xml"))
+                .build();
+        VirtualSystemApi api = requestSendsResponse(request, response)
+                .getVirtualSystemApi();
+
+        VSystem system = api.get("ABCDEFGH-A123B456CE");
+        assertNotNull(system, "system");
+    }
+
+    public void testGetDetails() {
+        HttpRequest request = buildGETWithQuery("Action=GetVSYSConfiguration&vsysId=ABCDEFGH-A123B456CE");
+        HttpResponse response = HttpResponse
+                .builder()
+                .statusCode(200)
+                .payload(
+                        payloadFromResource("/GetVSYSConfiguration-response.xml"))
+                .build();
+        VirtualSystemApi api = requestSendsResponse(request, response)
+                .getVirtualSystemApi();
+
+        VSystem system = api.getDetails("ABCDEFGH-A123B456CE");
+        assertNotNull(system, "system");
+    }
+
+    public void testGetStatus() {
+        HttpRequest request = buildGETWithQuery("Action=GetVSYSStatus"
+                + "&vsysId=ABCDEFGH-A123B456CE");
+        HttpResponse response = HttpResponse.builder().statusCode(200)
+                .payload(payloadFromResource("/GetVSYSStatus-response.xml"))
+                .build();
+        VirtualSystemApi api = requestSendsResponse(request, response)
+                .getVirtualSystemApi();
+
+        assertEquals(api.getStatus("ABCDEFGH-A123B456CE"), VSystemStatus.NORMAL);
+    }
+
+    public void testUpdate() {
+        HttpRequest request = buildGETWithQuery("Action=UpdateVSYSAttribute"
+                + "&vsysId=ABCDEFGH-A123B456CE" + "&attributeValue=new-name"
+                + "&attributeName=updateName");
+        HttpResponse response = HttpResponse
+                .builder()
+                .statusCode(200)
+                .payload(
+                        payloadFromResource("/UpdateVDiskAttribute-response.xml"))
+                .build();
+
+        VirtualSystemApi api = requestSendsResponse(request, response)
+                .getVirtualSystemApi();
+
+        api.update("ABCDEFGH-A123B456CE", "updateName", "new-name");
+    }
+
+    public void testListPublicIPs() {
+        HttpRequest request = buildGETWithQuery("Action=ListPublicIP"
+                + "&vsysId=ABCDEFGH-A123B456CE");
+        HttpResponse response = HttpResponse
+                .builder()
+                .statusCode(200)
+                .payload(
+                        payloadFromResource("/ListPublicIP_one_vsys-response.xml"))
+                .build();
+        VirtualSystemApi api = requestSendsResponse(request, response)
+                .getVirtualSystemApi();
+
+        Set<PublicIP> ips = api.listPublicIPs("ABCDEFGH-A123B456CE");
+        assertNotNull(ips, "ips");
+        assertTrue(ips.size() == 2, "Unexpected number of ips: " + ips.size());
+        assertEquals(ips.iterator().next().getVersion(), PublicIP.Version.IPv4);
+    }
+
+    public void testListServers() {
+        HttpRequest request = buildGETWithQuery("Action=ListVServer"
+                + "&vsysId=ABCDEFGH-A123B456CE");
+        HttpResponse response = HttpResponse
+                .builder()
+                .statusCode(200)
+                .payload(
+                        payloadFromResource("/ListVServer-response.xml"))
+                .build();
+        VirtualSystemApi api = requestSendsResponse(request, response)
+                .getVirtualSystemApi();
+
+        Set<VServer> servers = api.listServers("ABCDEFGH-A123B456CE");
+        assertNotNull(servers, "servers");
+        assertEquals(servers.size(), 2);
+    }
+
+    public void testDisks() {
+        HttpRequest request = buildGETWithQuery("Action=ListVDisk"
+                + "&vsysId=ABCDEFGH-A123B456CE");
+        HttpResponse response = HttpResponse
+                .builder()
+                .statusCode(200)
+                .payload(
+                        payloadFromResource("/ListVDisk-response.xml"))
+                .build();
+        VirtualSystemApi api = requestSendsResponse(request, response)
+                .getVirtualSystemApi();
+
+        Set<VDisk> disks = api.listDisks("ABCDEFGH-A123B456CE");
+        assertNotNull(disks, "disks");
+        assertEquals(disks.size(), 1);
+    }
+
+    public void testListBuiltinServers() {
+        HttpRequest request = buildGETWithQuery("Action=ListEFM"
+                + "&vsysId=ABCDEFGH-A123B456CE" + "&efmType=FW");
+        HttpResponse response = HttpResponse
+                .builder()
+                .statusCode(200)
+                .payload(
+                        payloadFromResource("/ListEFM-response.xml"))
+                .build();
+        VirtualSystemApi api = requestSendsResponse(request, response)
+                .getVirtualSystemApi();
+
+        Set<BuiltinServer> fws = api.listBuiltinServers("ABCDEFGH-A123B456CE", "FW");
+        assertNotNull(fws, "fws");
+        assertEquals(fws.size(), 1);
+    }
+
+    public void testAllocatePublicIP() {
+        HttpRequest request = buildGETWithQuery("Action=AllocatePublicIP&vsysId=ABCDEFGH-A123B456CE");
+        HttpResponse response = HttpResponse
+                .builder()
+                .statusCode(200)
+                .payload(
+                        payloadFromResource("/AllocatePublicIP-response.xml"))
+                .build();
+        VirtualSystemApi api = requestSendsResponse(request, response)
+                .getVirtualSystemApi();
+
+        api.allocatePublicIP("ABCDEFGH-A123B456CE");
+    }
+
+    public void testCreateBuiltinServer() {
+        HttpRequest request = buildGETWithQuery("Action=CreateEFM"
+                + "&efmType=SLB"
+                + "&efmName=web%20load%20balancer"
+                + "&networkId=ABCDEFGH-A123B456CE-N-DMZ"
+                + "&vsysId=ABCDEFGH-A123B456CE");
+        HttpResponse response = HttpResponse
+                .builder()
+                .statusCode(200)
+                .payload(
+                        payloadFromResource("/CreateEFM-response.xml"))
+                .build();
+        VirtualSystemApi api = requestSendsResponse(request, response)
+                .getVirtualSystemApi();
+
+        String id = api.createBuiltinServer("web load balancer",
+                "ABCDEFGH-A123B456CE-N-DMZ");
+        assertEquals(id, "CONTRACT-EFM00001");
+    }
+
+    public void testCreateServer() {
+        HttpRequest request = buildGETWithQuery("Action=CreateVServer"
+                + "&vserverName=vm1"
+                + "&diskImageId=IMG_A1B2C3_1234567890ABCD"
+                + "&vserverType=economy"
+                + "&networkId=ABCDEFGH-A123B456CE-N-DMZ"
+                + "&vsysId=ABCDEFGH-A123B456CE");
+        HttpResponse response = HttpResponse
+                .builder()
+                .statusCode(200)
+                .payload(
+                        payloadFromResource("/CreateVServer-response.xml"))
+                .build();
+        VirtualSystemApi api = requestSendsResponse(request, response)
+                .getVirtualSystemApi();
+
+        String id = api.createServer("vm1", "economy", "IMG_A1B2C3_1234567890ABCD",
+                "ABCDEFGH-A123B456CE-N-DMZ");
+        assertEquals(id, "ABCDEFGH-A123B456CE-S-0007");
+    }
+
+    public void testCreateDisk() {
+        HttpRequest request = buildGETWithQuery("Action=CreateVDisk"
+                + "&vsysId=ABCDEFGH-A123B456CE"
+                + "&size=10"
+                + "&vdiskName=disk1");
+        HttpResponse response = HttpResponse
+                .builder()
+                .statusCode(200)
+                .payload(
+                        payloadFromResource("/CreateVDisk-response.xml"))
+                .build();
+        VirtualSystemApi api = requestSendsResponse(request, response)
+                .getVirtualSystemApi();
+
+        String id = api.createDisk("ABCDEFGH-A123B456CE", "disk1", 10);
+        assertEquals(id, "ABCDEFGH-A123B456CE-S-0006");
+    }
+
+/*
+    public void testRegisterAsPrivateImage() {
+        HttpRequest request = buildGETWithQuery("Action=AllocatePublicIP&vsysId=ABCDEFGH-A123B456CE");
+        HttpResponse response = HttpResponse
+                .builder()
+                .statusCode(200)
+                .payload(
+                        payloadFromResource("/AllocatePublicIP-response.xml"))
+                .build();
+        VirtualSystemApi api = requestSendsResponse(request, response)
+                .getVirtualSystemApi();
+
+        api.registerAsPrivateVSYSDescriptor("ABCDEFGH-A123B456CE");
+    }
+*/
+}
diff --git a/labs/fgcp/src/test/java/org/jclouds/http/internal/HttpInternalsLiveTest.java b/labs/fgcp/src/test/java/org/jclouds/http/internal/HttpInternalsLiveTest.java
new file mode 100644
index 0000000..7ab8c2a
--- /dev/null
+++ b/labs/fgcp/src/test/java/org/jclouds/http/internal/HttpInternalsLiveTest.java
@@ -0,0 +1,38 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.http.internal;
+
+import static org.testng.Assert.assertNotNull;
+
+import org.jclouds.fujitsu.fgcp.services.BaseFGCPApiLiveTest;
+import org.testng.annotations.Test;
+
+/**
+ * Created by IntelliJ IDEA.
+ *
+ * @author Dies Koper
+ */
+@Test(groups = "live", enabled = true, singleThreaded = true, testName = "HttpInternalsLiveTest")
+public class HttpInternalsLiveTest extends BaseFGCPApiLiveTest {
+
+    @Test
+    public void testTrustedSSLContext() {
+    	assertNotNull(context.utils().injector().getInstance(JavaUrlHttpCommandExecutorService.class).sslContextSupplier);
+    }
+}
diff --git a/labs/fgcp/src/test/resources/certs/jclouds-test-fgcp.p12 b/labs/fgcp/src/test/resources/certs/jclouds-test-fgcp.p12
new file mode 100644
index 0000000..6ff5786
--- /dev/null
+++ b/labs/fgcp/src/test/resources/certs/jclouds-test-fgcp.p12
Binary files differ
diff --git a/labs/fgcp/src/test/resources/certs/jclouds-test-fgcp.pem b/labs/fgcp/src/test/resources/certs/jclouds-test-fgcp.pem
new file mode 100644
index 0000000..33da396
--- /dev/null
+++ b/labs/fgcp/src/test/resources/certs/jclouds-test-fgcp.pem
@@ -0,0 +1,35 @@
+Bag Attributes
+    friendlyName: test-fgcp
+    localKeyID: 54 69 6D 65 20 31 33 32 36 36 38 34 30 33 32 34 35 31 
+Key Attributes: <No Attributes>
+-----BEGIN RSA PRIVATE KEY-----
+MIICXAIBAAKBgQCHj9j4voqoMfTVvsAUjxoJYCz9cXpmRzkPwoxOOP99bc+xnIEe
+K8jOVrlCy0Zwr0fr+PZT15RX8tAzg69kP7WLiVBqYeW7TKZ+9b+HgxUvDd6aaj1C
+SVdgHyQPmpcBLe2E2ADvbeEWYFiqhm5ms8Qes/Hb7S5Ct/Ux4R9UUrDnYQIDAQAB
+AoGABkxrs1r/DEON8aR0PkBL4GWkkX4FRt1GTHIonLXPQR+qB8GSyjkUkmm7H9xc
+AH5UZCVkJI8eqFtyywHyU0EWiTyd3pjkXIuWPcmtydTN3LwY6UZww07g7cAjQNsw
+cSXDXfmpAWNoavJWsjd7EUQ1VnnJMDo8A3Jj8BgvF7mTlZUCQQDdMmmOJNBRmbZP
+i9jfuggupIHNoJEyI8hQM1LQdyDYMojFZ/hz09vzuWzO1J4XpHtCa2Vuxq9hvC5R
+6jKmcTI3AkEAnOQkvv2/2x7T6+7zx53xqFuGjHeNjuaHqTENoT2Gh0oug4IX0HPE
+PTw9yVDqDCQe72jeSZZDLpejdF9tcyNHJwJBAIOkC/PfbucRXtGqfdBwK4xutR2G
+UMMRTpaEZOXR8Aca1BD/1npAfKdpFBtnqAqUBhM6TSyHLDszPjHb+nbZ6TMCQGEM
+Mrq9xd6qDBbmQX+Z8LDepLThAvyBFyuOP0sc/slTFsCcSVTVN29VgzazSYNnGIep
+S88jFr2MaTyEBvTwvoMCQE9ZWyYcmpkHxH5X5j6Bpf+ksY6eLnlH/YSOa9Hw8vZY
+SR2RvvhAa4UovUoyYJ3p0U/pO/h/W0p5TxIA3V+y7CY=
+-----END RSA PRIVATE KEY-----
+Bag Attributes
+    friendlyName: CN=localhost
+    localKeyID: 54 69 6D 65 20 31 33 32 36 36 38 34 30 33 32 34 35 31 
+subject=/CN=localhost
+issuer=/CN=localhost
+-----BEGIN CERTIFICATE-----
+MIIBnzCCAQigAwIBAgIETxOXgDANBgkqhkiG9w0BAQUFADAUMRIwEAYDVQQDEwls
+b2NhbGhvc3QwHhcNMTIwMTE2MDMyMDMyWhcNMjcwMTEyMDMyMDMyWjAUMRIwEAYD
+VQQDEwlsb2NhbGhvc3QwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAIeP2Pi+
+iqgx9NW+wBSPGglgLP1xemZHOQ/CjE44/31tz7GcgR4ryM5WuULLRnCvR+v49lPX
+lFfy0DODr2Q/tYuJUGph5btMpn71v4eDFS8N3ppqPUJJV2AfJA+alwEt7YTYAO9t
+4RZgWKqGbmazxB6z8dvtLkK39THhH1RSsOdhAgMBAAEwDQYJKoZIhvcNAQEFBQAD
+gYEANbfXtBVCUIZiQCU5LP/vKoKZMpE5X6s+kDqTJ3vntuczkN0qFWKIi9WABwAa
+/Aq2IffJIu6rZgWchJqhN7+PeVOTfh9xRWE7QFHDrsuBYaicrki7RB1kKCQLtUpD
+aZB5xlm5FhT2Hzkgkawdo5keD/+OcDqKVK2fEK8W6r61Spc=
+-----END CERTIFICATE-----
diff --git a/labs/fgcp/src/test/resources/log4j.xml b/labs/fgcp/src/test/resources/log4j.xml
new file mode 100644
index 0000000..eb276c1
--- /dev/null
+++ b/labs/fgcp/src/test/resources/log4j.xml
@@ -0,0 +1,194 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!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">
+
+    <!-- ================================= -->
+    <!-- Preserve messages in A local file -->
+    <!-- ================================= -->
+
+    <!-- A time/date based rolling appender -->
+    <appender name="WIREFILE" class="org.apache.log4j.DailyRollingFileAppender">
+        <param name="File" value="/opt/jclouds-wire.log"/>
+        <param name="Append" value="true"/>
+
+        <!-- Rollover at midnight each day -->
+        <param name="DatePattern" value="'.'yyyy-MM-dd"/>
+
+        <param name="Threshold" value="TRACE"/>
+
+        <layout class="org.apache.log4j.PatternLayout">
+            <!-- The default pattern: Date Priority [Category] Message\n -->
+            <param name="ConversionPattern" value="%d %-5p [%c] (%t) %m%n"/>
+
+            <!--
+                The full pattern: Date MS Priority [Category]
+                (Thread:NDC) Message\n <param name="ConversionPattern"
+                value="%d %-5r %-5p [%c] (%t:%x) %m%n"/>
+            -->
+        </layout>
+    </appender>
+
+    <appender name="FILE" class="org.apache.log4j.DailyRollingFileAppender">
+
+        <errorHandler class="org.apache.log4j.helpers.OnlyOnceErrorHandler"/>
+        <param name="File" value="/opt/fgcp.log"/>
+        <param name="Append" value="true"/>
+
+        <param name="Threshold" value="TRACE"/>
+
+        <!-- Rollover at midnight each day -->
+        <param name="DatePattern" value="'.'yyyy-MM-dd"/>
+
+        <layout class="org.apache.log4j.PatternLayout">
+            <!-- The default pattern: Date Priority [Category] Message\n -->
+            <param name="ConversionPattern" value="%d %-5p [%c] %m%n"/>
+
+        </layout>
+    </appender>
+
+    <appender name="SSHFILE" class="org.apache.log4j.DailyRollingFileAppender">
+
+        <errorHandler class="org.apache.log4j.helpers.OnlyOnceErrorHandler"/>
+        <param name="File" value="/opt/fgcp-ssh.log"/>
+        <param name="Append" value="true"/>
+
+        <param name="Threshold" value="TRACE"/>
+
+        <!-- Rollover at midnight each day -->
+        <param name="DatePattern" value="'.'yyyy-MM-dd"/>
+
+        <layout class="org.apache.log4j.PatternLayout">
+            <!-- The default pattern: Date Priority [Category] Message\n -->
+            <param name="ConversionPattern" value="%d %-5p [%c] %m%n"/>
+
+        </layout>
+    </appender>
+
+    <!-- ============================== -->
+    <!-- Append messages to the console -->
+    <!-- ============================== -->
+
+    <appender name="CONSOLE" class="org.apache.log4j.ConsoleAppender">
+        <errorHandler class="org.apache.log4j.helpers.OnlyOnceErrorHandler"/>
+        <param name="Target" value="System.out"/>
+        <param name="Threshold" value="DEBUG"/>
+
+        <layout class="org.apache.log4j.PatternLayout">
+            <!-- The default pattern: Date Priority [Category] Message\n -->
+            <param name="ConversionPattern" value="%d{ABSOLUTE} %-5p [%c{1}] %m%n"/>
+        </layout>
+    </appender>
+
+    <!-- A time/date based rolling appender -->
+    <appender name="COMPUTEFILE" class="org.apache.log4j.DailyRollingFileAppender">
+        <param name="File" value="/opt/jclouds-compute.log"/>
+        <param name="Append" value="true"/>
+
+        <!-- Rollover at midnight each day -->
+        <param name="DatePattern" value="'.'yyyy-MM-dd"/>
+
+        <param name="Threshold" value="TRACE"/>
+
+        <layout class="org.apache.log4j.PatternLayout">
+            <!-- The default pattern: Date Priority [Category] Message\n -->
+            <param name="ConversionPattern" value="%d %-5p [%c] (%t) %m%n"/>
+
+            <!--
+                The full pattern: Date MS Priority [Category]
+                (Thread:NDC) Message\n <param name="ConversionPattern"
+                value="%d %-5r %-5p [%c] (%t:%x) %m%n"/>
+            -->
+        </layout>
+    </appender>
+
+    <!-- A time/date based rolling appender -->
+    <appender name="GOOGLEINJECTFILE" class="org.apache.log4j.DailyRollingFileAppender">
+        <param name="File" value="/opt/jclouds-google-inject.log"/>
+        <param name="Append" value="true"/>
+
+        <!-- Rollover at midnight each day -->
+        <param name="DatePattern" value="'.'yyyy-MM-dd"/>
+
+        <param name="Threshold" value="TRACE"/>
+
+        <layout class="org.apache.log4j.PatternLayout">
+            <!-- The default pattern: Date Priority [Category] Message\n -->
+            <param name="ConversionPattern" value="%d %-5p [%c] (%t) %m%n"/>
+
+        </layout>
+    </appender>
+
+    <appender name="ASYNCCOMPUTE" class="org.apache.log4j.AsyncAppender">
+        <appender-ref ref="COMPUTEFILE"/>
+    </appender>
+
+    <appender name="ASYNCSSH" class="org.apache.log4j.AsyncAppender">
+        <appender-ref ref="SSHFILE"/>
+    </appender>
+
+    <appender name="ASYNC" class="org.apache.log4j.AsyncAppender">
+        <appender-ref ref="FILE"/>
+    </appender>
+
+    <appender name="ASYNCWIRE" class="org.apache.log4j.AsyncAppender">
+        <appender-ref ref="WIREFILE"/>
+    </appender>
+
+    <appender name="GOOGLEINJECT" class="org.apache.log4j.AsyncAppender">
+        <appender-ref ref="GOOGLEINJECTFILE"/>
+    </appender>
+
+    <!-- ================ -->
+    <!-- Limit categories -->
+    <!-- ================ -->
+
+    <category name="org.jclouds.logging.internal">
+        <priority value="WARN"/>
+    </category>
+    <category name="org.apache.commons.httpclient">
+        <priority value="WARN"/>
+    </category>
+
+    <category name="org.jclouds">
+        <priority value="DEBUG"/>
+        <appender-ref ref="ASYNC"/>
+    </category>
+
+    <category name="jclouds.headers">
+        <priority value="DEBUG"/>
+        <appender-ref ref="ASYNCWIRE"/>
+    </category>
+
+    <category name="jclouds.ssh">
+        <priority value="DEBUG"/>
+        <appender-ref ref="ASYNCSSH"/>
+    </category>
+    <category name="jclouds.wire">
+        <priority value="DEBUG"/>
+        <appender-ref ref="ASYNCWIRE"/>
+    </category>
+    <category name="jclouds.compute">
+        <priority value="TRACE"/>
+        <appender-ref ref="ASYNCCOMPUTE"/>
+    </category>
+
+    <category name="com.google.inject">
+        <priority value="ALL"/>
+        <appender-ref ref="GOOGLEINJECT"/>
+    </category>
+
+    <!-- ======================= -->
+    <!-- Setup the Root category -->
+    <!-- ======================= -->
+
+    <root>
+        <appender-ref ref="FILE"/>
+        <appender-ref ref="CONSOLE"/>
+    </root>
+
+</log4j:configuration>
diff --git a/labs/fgcp/src/test/resources/logback.xml b/labs/fgcp/src/test/resources/logback.xml
new file mode 100644
index 0000000..a4a6a3f
--- /dev/null
+++ b/labs/fgcp/src/test/resources/logback.xml
@@ -0,0 +1,64 @@
+<?xml version="1.0"?>
+<configuration scan="false" >
+    <appender name="FILE" class="ch.qos.logback.core.FileAppender">
+        <file>target/test-data/jclouds.log</file>
+
+        <encoder>
+            <Pattern>%d %-5p [%c] [%thread] %m%n</Pattern>
+        </encoder>
+    </appender>
+
+    <appender name="WIREFILE" class="ch.qos.logback.core.FileAppender">
+        <file>target/test-data/jclouds-wire.log</file>
+
+        <encoder>
+            <Pattern>%d %-5p [%c] [%thread] %m%n</Pattern>
+        </encoder>
+    </appender>
+
+    <appender name="COMPUTEFILE" class="ch.qos.logback.core.FileAppender">
+        <file>target/test-data/jclouds-compute.log</file>
+
+        <encoder>
+            <Pattern>%d %-5p [%c] [%thread] %m%n</Pattern>
+        </encoder>
+    </appender>
+    
+    <appender name="SSHFILE" class="ch.qos.logback.core.FileAppender">
+        <file>target/test-data/jclouds-ssh.log</file>
+
+        <encoder>
+            <Pattern>%d %-5p [%c] [%thread] %m%n</Pattern>
+        </encoder>
+    </appender>
+
+    <root>
+        <level value="warn" />
+    </root>
+
+    <logger name="org.jclouds">
+        <level value="DEBUG" />
+        <appender-ref ref="FILE" />
+    </logger>
+
+    <logger name="jclouds.wire">
+        <level value="DEBUG" />
+        <appender-ref ref="WIREFILE" />
+    </logger>
+
+    <logger name="jclouds.headers">
+        <level value="DEBUG" />
+        <appender-ref ref="WIREFILE" />
+    </logger>
+
+    <logger name="jclouds.compute">
+        <level value="DEBUG" />
+        <appender-ref ref="COMPUTEFILE" />
+    </logger>
+    
+    <logger name="jclouds.ssh">
+        <level value="DEBUG" />
+        <appender-ref ref="SSHFILE" />
+    </logger>
+
+</configuration>
\ No newline at end of file
diff --git a/labs/fgcp/src/test/resources/requests/CreateVSYS-request.xml b/labs/fgcp/src/test/resources/requests/CreateVSYS-request.xml
new file mode 100644
index 0000000..8dd318b
--- /dev/null
+++ b/labs/fgcp/src/test/resources/requests/CreateVSYS-request.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<OViSSRequest>
+  <Action>CreateVSYS</Action>
+  <vsysDescriptorId>myDescId</vsysDescriptorId>
+  <vsysName>myVSYS</vsysName>
+  <Version>2011-01-31</Version>
+  <Locale>en</Locale>
+  <AccessKeyId>R01ULTA5OjAwJjEyMzQ1Njc4OTAmMS4wJlNIQTF3aXRoUlNB</AccessKeyId>
+  <Signature>G2rGfLAkbq0IURQfXIWYxj3BnMGbjRk4KPnZLAze3Lt4SMMRt8lkjqKvR5Cm+nFpDN7J6IprVCCsIrRq5BqPeXT6xtWyb6qMNds2BAr1h/JePGs0UosOh2tgPUMSFlZwLVjgNyrSa2zeHA3AEHjF6H1jqcWXXqfCAD4SOHaNavk=</Signature>
+</OViSSRequest>
\ No newline at end of file
diff --git a/labs/fgcp/src/test/resources/responses/AddAddressRange-response.xml b/labs/fgcp/src/test/resources/responses/AddAddressRange-response.xml
new file mode 100644
index 0000000..81265be
--- /dev/null
+++ b/labs/fgcp/src/test/resources/responses/AddAddressRange-response.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<AddAddressRangeResponse xmlns="http://apioviss.jp.fujitsu.com">
+  <responseMessage>Processing was completed.</responseMessage>
+  <responseStatus>SUCCESS</responseStatus>
+</AddAddressRangeResponse>
\ No newline at end of file
diff --git a/labs/fgcp/src/test/resources/responses/AllocatePublicIP-response.xml b/labs/fgcp/src/test/resources/responses/AllocatePublicIP-response.xml
new file mode 100644
index 0000000..4411beb
--- /dev/null
+++ b/labs/fgcp/src/test/resources/responses/AllocatePublicIP-response.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<AllocatePublicIPResponse xmlns="http://apioviss.jp.fujitsu.com">
+  <responseMessage>Processing was completed.</responseMessage>
+  <responseStatus>SUCCESS</responseStatus>
+</AllocatePublicIPResponse>
\ No newline at end of file
diff --git a/labs/fgcp/src/test/resources/responses/AttachPublicIP-response.xml b/labs/fgcp/src/test/resources/responses/AttachPublicIP-response.xml
new file mode 100644
index 0000000..bcc457f
--- /dev/null
+++ b/labs/fgcp/src/test/resources/responses/AttachPublicIP-response.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<AttachPublicIPResponse xmlns="http://apioviss.jp.fujitsu.com">
+  <responseMessage>Processing was completed.</responseMessage>
+  <responseStatus>SUCCESS</responseStatus>
+</AttachPublicIPResponse>
\ No newline at end of file
diff --git a/labs/fgcp/src/test/resources/responses/AttachVDisk-response.xml b/labs/fgcp/src/test/resources/responses/AttachVDisk-response.xml
new file mode 100644
index 0000000..0a38583
--- /dev/null
+++ b/labs/fgcp/src/test/resources/responses/AttachVDisk-response.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<AttachVDiskResponse xmlns="http://apioviss.jp.fujitsu.com">
+  <responseMessage>Processing was completed.</responseMessage>
+  <responseStatus>SUCCESS</responseStatus>
+</AttachVDiskResponse>
\ No newline at end of file
diff --git a/labs/fgcp/src/test/resources/responses/BackupEFM-response.xml b/labs/fgcp/src/test/resources/responses/BackupEFM-response.xml
new file mode 100644
index 0000000..39e69e3
--- /dev/null
+++ b/labs/fgcp/src/test/resources/responses/BackupEFM-response.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<BackupEFMResponse xmlns="http://apioviss.jp.fujitsu.com">
+  <responseMessage>Processing was completed.</responseMessage>
+  <responseStatus>SUCCESS</responseStatus>
+</BackupEFMResponse>
\ No newline at end of file
diff --git a/labs/fgcp/src/test/resources/responses/BackupVDisk-response.xml b/labs/fgcp/src/test/resources/responses/BackupVDisk-response.xml
new file mode 100644
index 0000000..0018289
--- /dev/null
+++ b/labs/fgcp/src/test/resources/responses/BackupVDisk-response.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<BackupVDiskResponse xmlns="http://apioviss.jp.fujitsu.com">
+  <responseMessage>Processing was completed.</responseMessage>
+  <responseStatus>SUCCESS</responseStatus>
+</BackupVDiskResponse>
\ No newline at end of file
diff --git a/labs/fgcp/src/test/resources/responses/CreateAddressPool-response.xml b/labs/fgcp/src/test/resources/responses/CreateAddressPool-response.xml
new file mode 100644
index 0000000..17988f5
--- /dev/null
+++ b/labs/fgcp/src/test/resources/responses/CreateAddressPool-response.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<CreateAddressPoolResponse xmlns="http://apioviss.jp.fujitsu.com">
+  <responseMessage>Processing was completed.</responseMessage>
+  <responseStatus>SUCCESS</responseStatus>
+</CreateAddressPoolResponse>
\ No newline at end of file
diff --git a/labs/fgcp/src/test/resources/responses/CreateEFM-response.xml b/labs/fgcp/src/test/resources/responses/CreateEFM-response.xml
new file mode 100644
index 0000000..bd20f9a
--- /dev/null
+++ b/labs/fgcp/src/test/resources/responses/CreateEFM-response.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<CreateEFMResponse xmlns="http://apioviss.jp.fujitsu.com">
+  <responseMessage>Processing was completed.</responseMessage>
+  <responseStatus>SUCCESS</responseStatus>
+  <efmId>CONTRACT-EFM00001</efmId>
+</CreateEFMResponse>
\ No newline at end of file
diff --git a/labs/fgcp/src/test/resources/responses/CreateVDisk-response.xml b/labs/fgcp/src/test/resources/responses/CreateVDisk-response.xml
new file mode 100644
index 0000000..ae7d8a3
--- /dev/null
+++ b/labs/fgcp/src/test/resources/responses/CreateVDisk-response.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<CreateVDiskResponse xmlns="http://apioviss.jp.fujitsu.com">
+  <responseMessage>Processing was completed.</responseMessage>
+  <responseStatus>SUCCESS</responseStatus>
+  <vdiskId>ABCDEFGH-A123B456CE-S-0006</vdiskId>
+</CreateVDiskResponse>
\ No newline at end of file
diff --git a/labs/fgcp/src/test/resources/responses/CreateVSYS-response.xml b/labs/fgcp/src/test/resources/responses/CreateVSYS-response.xml
new file mode 100644
index 0000000..425cbc7
--- /dev/null
+++ b/labs/fgcp/src/test/resources/responses/CreateVSYS-response.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<CreateVSYSResponse xmlns="http://apioviss.jp.fujitsu.com">
+  <responseMessage>Processing was completed.</responseMessage>
+  <responseStatus>SUCCESS</responseStatus>
+  <vsysId>CONTRACT-VSYS00001</vsysId>
+</CreateVSYSResponse>
\ No newline at end of file
diff --git a/labs/fgcp/src/test/resources/responses/CreateVServer-response.xml b/labs/fgcp/src/test/resources/responses/CreateVServer-response.xml
new file mode 100644
index 0000000..81c51b9
--- /dev/null
+++ b/labs/fgcp/src/test/resources/responses/CreateVServer-response.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<CreateVServerResponse xmlns="http://apioviss.jp.fujitsu.com">
+  <responseMessage>Processing was completed.</responseMessage>
+  <responseStatus>SUCCESS</responseStatus>
+  <vserverId>ABCDEFGH-A123B456CE-S-0007</vserverId>
+</CreateVServerResponse>
\ No newline at end of file
diff --git a/labs/fgcp/src/test/resources/responses/DeleteAddressRange-response.xml b/labs/fgcp/src/test/resources/responses/DeleteAddressRange-response.xml
new file mode 100644
index 0000000..e3cdd50
--- /dev/null
+++ b/labs/fgcp/src/test/resources/responses/DeleteAddressRange-response.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<DeleteAddressRangeResponse xmlns="http://apioviss.jp.fujitsu.com">
+  <responseMessage>Processing was completed.</responseMessage>
+  <responseStatus>SUCCESS</responseStatus>
+</DeleteAddressRangeResponse>
\ No newline at end of file
diff --git a/labs/fgcp/src/test/resources/responses/DestroyEFM-response.xml b/labs/fgcp/src/test/resources/responses/DestroyEFM-response.xml
new file mode 100644
index 0000000..aa8e374
--- /dev/null
+++ b/labs/fgcp/src/test/resources/responses/DestroyEFM-response.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<DestroyEFMResponse xmlns="http://apioviss.jp.fujitsu.com">
+  <responseMessage>Processing was completed.</responseMessage>
+  <responseStatus>SUCCESS</responseStatus>
+</DestroyEFMResponse>
\ No newline at end of file
diff --git a/labs/fgcp/src/test/resources/responses/DestroyEFMBackup-response.xml b/labs/fgcp/src/test/resources/responses/DestroyEFMBackup-response.xml
new file mode 100644
index 0000000..a2da3c4
--- /dev/null
+++ b/labs/fgcp/src/test/resources/responses/DestroyEFMBackup-response.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<DestroyEFMBackupResponse xmlns="http://apioviss.jp.fujitsu.com">
+  <responseMessage>Processing was completed.</responseMessage>
+  <responseStatus>SUCCESS</responseStatus>
+</DestroyEFMBackupResponse>
\ No newline at end of file
diff --git a/labs/fgcp/src/test/resources/responses/DestroyVDisk-response.xml b/labs/fgcp/src/test/resources/responses/DestroyVDisk-response.xml
new file mode 100644
index 0000000..c66a6a9
--- /dev/null
+++ b/labs/fgcp/src/test/resources/responses/DestroyVDisk-response.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<DestroyVDiskResponse xmlns="http://apioviss.jp.fujitsu.com">
+  <responseMessage>Processing was completed.</responseMessage>
+  <responseStatus>SUCCESS</responseStatus>
+</DestroyVDiskResponse>
\ No newline at end of file
diff --git a/labs/fgcp/src/test/resources/responses/DestroyVDiskBackup-response.xml b/labs/fgcp/src/test/resources/responses/DestroyVDiskBackup-response.xml
new file mode 100644
index 0000000..af0088f
--- /dev/null
+++ b/labs/fgcp/src/test/resources/responses/DestroyVDiskBackup-response.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<DestroyVDiskBackupResponse xmlns="http://apioviss.jp.fujitsu.com">
+  <responseMessage>Processing was completed.</responseMessage>
+  <responseStatus>SUCCESS</responseStatus>
+</DestroyVDiskBackupResponse>
\ No newline at end of file
diff --git a/labs/fgcp/src/test/resources/responses/DestroyVServer-response.xml b/labs/fgcp/src/test/resources/responses/DestroyVServer-response.xml
new file mode 100644
index 0000000..c9fbbd2
--- /dev/null
+++ b/labs/fgcp/src/test/resources/responses/DestroyVServer-response.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<DestroyVServerResponse xmlns="http://apioviss.jp.fujitsu.com">
+  <responseMessage>Processing was completed.</responseMessage>
+  <responseStatus>SUCCESS</responseStatus>
+</DestroyVServerResponse>
\ No newline at end of file
diff --git a/labs/fgcp/src/test/resources/responses/DetachPublicIP-response.xml b/labs/fgcp/src/test/resources/responses/DetachPublicIP-response.xml
new file mode 100644
index 0000000..ee99b2e
--- /dev/null
+++ b/labs/fgcp/src/test/resources/responses/DetachPublicIP-response.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<DetachPublicIPResponse xmlns="http://apioviss.jp.fujitsu.com">
+  <responseMessage>Processing was completed.</responseMessage>
+  <responseStatus>SUCCESS</responseStatus>
+</DetachPublicIPResponse>
\ No newline at end of file
diff --git a/labs/fgcp/src/test/resources/responses/DetachVDisk-response.xml b/labs/fgcp/src/test/resources/responses/DetachVDisk-response.xml
new file mode 100644
index 0000000..877cb74
--- /dev/null
+++ b/labs/fgcp/src/test/resources/responses/DetachVDisk-response.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<DetachVDiskResponse xmlns="http://apioviss.jp.fujitsu.com">
+  <responseMessage>Processing was completed.</responseMessage>
+  <responseStatus>SUCCESS</responseStatus>
+</DetachVDiskResponse>
\ No newline at end of file
diff --git a/labs/fgcp/src/test/resources/responses/FreePublicIP-response.xml b/labs/fgcp/src/test/resources/responses/FreePublicIP-response.xml
new file mode 100644
index 0000000..7644e11
--- /dev/null
+++ b/labs/fgcp/src/test/resources/responses/FreePublicIP-response.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<FreePublicIPResponse xmlns="http://apioviss.jp.fujitsu.com">
+  <responseMessage>Processing was completed.</responseMessage>
+  <responseStatus>SUCCESS</responseStatus>
+</FreePublicIPResponse>
\ No newline at end of file
diff --git a/labs/fgcp/src/test/resources/responses/GetAddressRange-response.xml b/labs/fgcp/src/test/resources/responses/GetAddressRange-response.xml
new file mode 100644
index 0000000..2eb92bd
--- /dev/null
+++ b/labs/fgcp/src/test/resources/responses/GetAddressRange-response.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<GetAddressRangeResponse xmlns="http://apioviss.jp.fujitsu.com">
+  <addressranges>
+    <addressrange>
+      <from>192.168.0.0</from>
+      <range>MANUAL</range>
+      <to>192.168.255.255</to>
+    </addressrange>
+  </addressranges>
+  <responseMessage>Processing was completed.</responseMessage>
+  <responseStatus>SUCCESS</responseStatus>
+</GetAddressRangeResponse>
diff --git a/labs/fgcp/src/test/resources/responses/GetDiskImageAttributes-response.xml b/labs/fgcp/src/test/resources/responses/GetDiskImageAttributes-response.xml
new file mode 100644
index 0000000..044d31d
--- /dev/null
+++ b/labs/fgcp/src/test/resources/responses/GetDiskImageAttributes-response.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<GetDiskImageAttributesResponse xmlns="http://apioviss.jp.fujitsu.com">
+  <diskimage>
+    <creatorName>ABCDEFGH</creatorName>
+    <description />
+    <diskimageId>IMG_A1B2C3_1234567890ABCD</diskimageId>
+    <diskimageName>CentOS 6.0 64bit(EN)</diskimageName>
+    <licenseInfo />
+    <osName>CentOS 6.0 64bit (English)</osName>
+    <osType>pv</osType>
+    <registrant>ABCDEFGH</registrant>
+    <size>10.0</size>
+  </diskimage>
+  <responseMessage>Processing was completed.</responseMessage>
+  <responseStatus>SUCCESS</responseStatus>
+</GetDiskImageAttributesResponse>
diff --git a/labs/fgcp/src/test/resources/responses/GetEFMAttributes-response.xml b/labs/fgcp/src/test/resources/responses/GetEFMAttributes-response.xml
new file mode 100644
index 0000000..02f7bfe
--- /dev/null
+++ b/labs/fgcp/src/test/resources/responses/GetEFMAttributes-response.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<GetEFMAttributesResponse xmlns="http://apioviss.jp.fujitsu.com">
+  <efm>
+    <creator>CONTRACT-VSYS00001</creator>
+    <efmId>CONTRACT-VSYS00001-S-0001</efmId>
+    <efmName>Firewall</efmName>
+    <efmType>FW</efmType>
+  </efm>
+  <responseMessage>Processing was completed.</responseMessage>
+  <responseStatus>SUCCESS</responseStatus>
+</GetEFMAttributesResponse>
diff --git a/labs/fgcp/src/test/resources/responses/GetEFMStatus-response.xml b/labs/fgcp/src/test/resources/responses/GetEFMStatus-response.xml
new file mode 100644
index 0000000..960d939
--- /dev/null
+++ b/labs/fgcp/src/test/resources/responses/GetEFMStatus-response.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<GetEFMStatusResponse xmlns="http://apioviss.jp.fujitsu.com">
+  <responseMessage>Processing was completed.</responseMessage>
+  <responseStatus>SUCCESS</responseStatus>
+  <efmStatus>RUNNING</efmStatus>
+</GetEFMStatusResponse>
\ No newline at end of file
diff --git a/labs/fgcp/src/test/resources/responses/GetEventLog-response.xml b/labs/fgcp/src/test/resources/responses/GetEventLog-response.xml
new file mode 100644
index 0000000..6d757f9
--- /dev/null
+++ b/labs/fgcp/src/test/resources/responses/GetEventLog-response.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<GetEventLogResponse xmlns="http://apioviss.jp.fujitsu.com">
+  <responseMessage>Processing was completed.</responseMessage>
+  <responseStatus>SUCCESS</responseStatus>
+</GetEventLogResponse>
\ No newline at end of file
diff --git a/labs/fgcp/src/test/resources/responses/GetPerformanceInformation-response.xml b/labs/fgcp/src/test/resources/responses/GetPerformanceInformation-response.xml
new file mode 100644
index 0000000..f34995a
--- /dev/null
+++ b/labs/fgcp/src/test/resources/responses/GetPerformanceInformation-response.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<GetPerformanceInformationResponse xmlns="http://apioviss.jp.fujitsu.com">
+  <interval>10minute</interval>
+  <responseMessage>Processing was completed.</responseMessage>
+  <responseStatus>SUCCESS</responseStatus>
+  <serverId>CONTRACT-VSYS00001-S-0001</serverId>
+  <serverName>my server</serverName>
+  <serverType>GENERAL</serverType>
+</GetPerformanceInformationResponse>
\ No newline at end of file
diff --git a/labs/fgcp/src/test/resources/responses/GetPublicIPAttributes-response.xml b/labs/fgcp/src/test/resources/responses/GetPublicIPAttributes-response.xml
new file mode 100644
index 0000000..c9cc639
--- /dev/null
+++ b/labs/fgcp/src/test/resources/responses/GetPublicIPAttributes-response.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<GetPublicIPAttributesResponse xmlns="http://apioviss.jp.fujitsu.com">
+  <publicips>
+    <publicip>
+      <address>123.45.67.89</address>
+      <v4v6Flag>IPv4</v4v6Flag>
+    </publicip>
+  </publicips>
+  <responseMessage>Processing was completed.</responseMessage>
+  <responseStatus>SUCCESS</responseStatus>
+</GetPublicIPAttributesResponse>
\ No newline at end of file
diff --git a/labs/fgcp/src/test/resources/responses/GetPublicIPStatus-response.xml b/labs/fgcp/src/test/resources/responses/GetPublicIPStatus-response.xml
new file mode 100644
index 0000000..d8eb549
--- /dev/null
+++ b/labs/fgcp/src/test/resources/responses/GetPublicIPStatus-response.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<GetPublicIPStatusResponse xmlns="http://apioviss.jp.fujitsu.com">
+  <publicipStatus>ATTACHED</publicipStatus>
+  <responseMessage>Processing was completed.</responseMessage>
+  <responseStatus>SUCCESS</responseStatus>
+</GetPublicIPStatusResponse>
\ No newline at end of file
diff --git a/labs/fgcp/src/test/resources/responses/GetVDiskAttributes-response.xml b/labs/fgcp/src/test/resources/responses/GetVDiskAttributes-response.xml
new file mode 100644
index 0000000..b0faecc
--- /dev/null
+++ b/labs/fgcp/src/test/resources/responses/GetVDiskAttributes-response.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<GetVDiskAttributesResponse xmlns="http://apioviss.jp.fujitsu.com">
+  <responseMessage>Processing was completed.</responseMessage>
+  <responseStatus>SUCCESS</responseStatus>
+  <vdisk>
+    <attachedTo>CONTRACT-VSYS00001-D-0001</attachedTo>
+    <creator>CONTRACT</creator>
+    <size>10.0</size>
+    <vdiskId>CONTRACT-VSYS00001-S-0006</vdiskId>
+    <vdiskName>disk1</vdiskName>
+  </vdisk>
+</GetVDiskAttributesResponse>
\ No newline at end of file
diff --git a/labs/fgcp/src/test/resources/responses/GetVDiskStatus-response.xml b/labs/fgcp/src/test/resources/responses/GetVDiskStatus-response.xml
new file mode 100644
index 0000000..5a0709a
--- /dev/null
+++ b/labs/fgcp/src/test/resources/responses/GetVDiskStatus-response.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<GetVDiskStatusResponse xmlns="http://apioviss.jp.fujitsu.com">
+  <responseMessage>Processing was completed.</responseMessage>
+  <responseStatus>SUCCESS</responseStatus>
+  <vdiskStatus>STOPPED</vdiskStatus>
+</GetVDiskStatusResponse>
\ No newline at end of file
diff --git a/labs/fgcp/src/test/resources/responses/GetVSYSAttributes-response.xml b/labs/fgcp/src/test/resources/responses/GetVSYSAttributes-response.xml
new file mode 100644
index 0000000..8f1044f
--- /dev/null
+++ b/labs/fgcp/src/test/resources/responses/GetVSYSAttributes-response.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<GetVSYSAttributesResponse xmlns="http://apioviss.jp.fujitsu.com">
+  <responseMessage>Processing was completed.</responseMessage>
+  <responseStatus>SUCCESS</responseStatus>
+  <vsys>
+    <baseDescriptor>2-tier Skeleton</baseDescriptor>
+    <creator>ABCDEFGH</creator>
+    <description>2-tier Skeleton</description>
+    <vsysId>ABCDEFGH-I123J456K</vsysId>
+    <vsysName>my virtual system</vsysName>
+  </vsys>
+</GetVSYSAttributesResponse>
diff --git a/labs/fgcp/src/test/resources/responses/GetVSYSConfiguration-response.xml b/labs/fgcp/src/test/resources/responses/GetVSYSConfiguration-response.xml
new file mode 100644
index 0000000..ca01590
--- /dev/null
+++ b/labs/fgcp/src/test/resources/responses/GetVSYSConfiguration-response.xml
@@ -0,0 +1,78 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<GetVSYSConfigurationResponse xmlns="http://apioviss.jp.fujitsu.com">
+  <responseMessage>Processing was completed.</responseMessage>
+  <responseStatus>SUCCESS</responseStatus>
+  <vsys>
+    <baseDescriptor>2-tier Skeleton</baseDescriptor>
+    <cloudCategory>NONE</cloudCategory>
+    <creator>ABCDEFGH</creator>
+    <description>2-tier Skeleton</description>
+    <vdisks>
+      <vdisk>
+        <creator>ABCDEFGH</creator>
+        <size>10.0</size>
+        <vdiskId>ABCDEFGH-I123J456K-D-0001</vdiskId>
+        <vdiskName>DISK1</vdiskName>
+      </vdisk>
+    </vdisks>
+    <vnets>
+      <vnet>
+        <networkId>ABCDEFGH-I123J456K-N-DMZ</networkId>
+      </vnet>
+      <vnet>
+        <networkId>ABCDEFGH-I123J456K-N-SECURE1</networkId>
+      </vnet>
+    </vnets>
+    <vservers>
+      <vserver>
+        <creator>ABCDEFGH</creator>
+        <diskimageId>IMG_A1B2C3_1234567890ABCD</diskimageId>
+        <vnics>
+          <vnic>
+            <networkId>ABCDEFGH-I123J456K-N-DMZ</networkId>
+            <nicNo>4</nicNo>
+            <privateIp>192.168.32.11</privateIp>
+          </vnic>
+          <vnic>
+            <networkId>ABCDEFGH-I123J456K-N-SECURE1</networkId>
+            <nicNo>5</nicNo>
+            <privateIp>192.168.33.11</privateIp>
+          </vnic>
+        </vnics>
+        <vserverId>ABCDEFGH-I123J456K-S-0001</vserverId>
+        <vserverName>Firewall</vserverName>
+        <vserverType>economy</vserverType>
+      </vserver>
+      <vserver>
+        <creator>ABCDEFGH</creator>
+        <diskimageId>IMG_A1B2C3_1234567890ABCD</diskimageId>
+        <vnics>
+          <vnic>
+            <networkId>ABCDEFGH-I123J456K-N-DMZ</networkId>
+            <nicNo>0</nicNo>
+            <privateIp>192.168.32.13</privateIp>
+          </vnic>
+        </vnics>
+        <vserverId>ABCDEFGH-I123J456K-S-0003</vserverId>
+        <vserverName>CentOS 6.3 32bit(EN)1</vserverName>
+        <vserverType>economy</vserverType>
+      </vserver>
+      <vserver>
+        <creator>ABCDEFGH</creator>
+        <diskimageId>IMG_A1B2C3_1234567890ABCD</diskimageId>
+        <vnics>
+          <vnic>
+            <networkId>ABCDEFGH-I123J456K-N-SECURE1</networkId>
+            <nicNo>0</nicNo>
+            <privateIp>192.168.33.12</privateIp>
+          </vnic>
+        </vnics>
+        <vserverId>ABCDEFGH-I123J456K-S-0004</vserverId>
+        <vserverName>CentOS 6.3 32bit(EN)2</vserverName>
+        <vserverType>economy</vserverType>
+      </vserver>
+    </vservers>
+    <vsysId>ABCDEFGH-I123J456K</vsysId>
+    <vsysName>system 2</vsysName>
+  </vsys>
+</GetVSYSConfigurationResponse>
\ No newline at end of file
diff --git a/labs/fgcp/src/test/resources/responses/GetVSYSDescriptorConfiguration-response.xml b/labs/fgcp/src/test/resources/responses/GetVSYSDescriptorConfiguration-response.xml
new file mode 100644
index 0000000..5fa9adb
--- /dev/null
+++ b/labs/fgcp/src/test/resources/responses/GetVSYSDescriptorConfiguration-response.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<GetVSYSDescriptorConfigurationResponse xmlns="http://apioviss.jp.fujitsu.com">
+  <responseMessage>Processing was completed.</responseMessage>
+  <responseStatus>SUCCESS</responseStatus>
+  <vsysdescriptor>
+    <creatorName>ABCDEFGH</creatorName>
+    <description>3-tier Skeleton</description>
+    <keyword>3-tier,Skeleton</keyword>
+    <registrant>ABCDEFGH</registrant>
+    <vservers>
+      <vserver>
+        <creator>ABCDEFGH</creator>
+        <diskimageId>IMG_A1B2C3_1234567890ABCD</diskimageId>
+        <vserverName>Firewall</vserverName>
+        <vserverType>economy</vserverType>
+      </vserver>
+    </vservers>
+    <vsysdescriptorId>3-tier Skeleton</vsysdescriptorId>
+    <vsysdescriptorName>3-tier Skeleton</vsysdescriptorName>
+  </vsysdescriptor>
+</GetVSYSDescriptorConfigurationResponse>
diff --git a/labs/fgcp/src/test/resources/responses/GetVSYSStatus-response.xml b/labs/fgcp/src/test/resources/responses/GetVSYSStatus-response.xml
new file mode 100644
index 0000000..552d4a2
--- /dev/null
+++ b/labs/fgcp/src/test/resources/responses/GetVSYSStatus-response.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<GetVSYSStatusResponse xmlns="http://apioviss.jp.fujitsu.com">
+  <responseMessage>Processing was completed.</responseMessage>
+  <responseStatus>SUCCESS</responseStatus>
+  <vsysStatus>NORMAL</vsysStatus>
+</GetVSYSStatusResponse>
diff --git a/labs/fgcp/src/test/resources/responses/GetVServerAttributes-response.xml b/labs/fgcp/src/test/resources/responses/GetVServerAttributes-response.xml
new file mode 100644
index 0000000..a18730e
--- /dev/null
+++ b/labs/fgcp/src/test/resources/responses/GetVServerAttributes-response.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<GetVServerAttributesResponse xmlns="http://apioviss.jp.fujitsu.com">
+  <responseMessage>Processing was completed.</responseMessage>
+  <responseStatus>SUCCESS</responseStatus>
+  <vserver>
+    <creator>CONTRACT</creator>
+    <diskimageId>IMG_A1B2C3_1234567890ABCD</diskimageId>
+    <vserverId>CONTRACT-VSYS00001-S-0001</vserverId>
+    <vserverName>my VM</vserverName>
+    <vserverType>economy</vserverType>
+  </vserver>
+</GetVServerAttributesResponse>
diff --git a/labs/fgcp/src/test/resources/responses/GetVServerConfiguration-response.xml b/labs/fgcp/src/test/resources/responses/GetVServerConfiguration-response.xml
new file mode 100644
index 0000000..36a8574
--- /dev/null
+++ b/labs/fgcp/src/test/resources/responses/GetVServerConfiguration-response.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<GetVServerConfigurationResponse xmlns="http://apioviss.jp.fujitsu.com">
+  <responseMessage>Processing was completed.</responseMessage>
+  <responseStatus>SUCCESS</responseStatus>
+  <vserver>
+    <creator>CONTRACT</creator>
+    <diskimageId>IMG_A1B2C3_1234567890ABCD</diskimageId>
+    <image>
+      <cpuBit>32</cpuBit>
+      <id>IMG_A1B2C3_1234567890ABCD</id>
+      <numOfMaxDisk>14</numOfMaxDisk>
+      <numOfMaxNic>8</numOfMaxNic>
+      <serverApplication>AP</serverApplication>
+      <serverCategory>GENERAL</serverCategory>
+      <softwares>
+        <software>
+          <category>OS</category>
+          <id>SW00000001</id>
+          <license />
+          <name>CentOS 5.4 32bit (English)</name>
+          <officialVersion>5.4</officialVersion>
+          <patch />
+          <support />
+          <version>5.4</version>
+        </software>
+      </softwares>
+      <sysvolSize>10.0</sysvolSize>
+    </image>
+    <vnics>
+      <vnic>
+        <networkId>CONTRACT-VSYS00001-N-DMZ</networkId>
+        <nicNo>0</nicNo>
+        <privateIp>192.168.4.13</privateIp>
+      </vnic>
+    </vnics>
+    <vserverId>CONTRACT-VSYS00001-S-0005</vserverId>
+    <vserverName>my VM</vserverName>
+    <vserverType>economy</vserverType>
+  </vserver>
+</GetVServerConfigurationResponse>
diff --git a/labs/fgcp/src/test/resources/responses/GetVServerInitialPassword-response.xml b/labs/fgcp/src/test/resources/responses/GetVServerInitialPassword-response.xml
new file mode 100644
index 0000000..c4816ed
--- /dev/null
+++ b/labs/fgcp/src/test/resources/responses/GetVServerInitialPassword-response.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<GetVServerInitialPasswordResponse xmlns="http://apioviss.jp.fujitsu.com">
+  <initialPassword>mySecretpwd1</initialPassword>
+  <responseMessage>Processing was completed.</responseMessage>
+  <responseStatus>SUCCESS</responseStatus>
+</GetVServerInitialPasswordResponse>
diff --git a/labs/fgcp/src/test/resources/responses/GetVServerStatus-response.xml b/labs/fgcp/src/test/resources/responses/GetVServerStatus-response.xml
new file mode 100644
index 0000000..d36f0fc
--- /dev/null
+++ b/labs/fgcp/src/test/resources/responses/GetVServerStatus-response.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<GetVServerStatusResponse xmlns="http://apioviss.jp.fujitsu.com">
+  <responseMessage>Processing was completed.</responseMessage>
+  <responseStatus>SUCCESS</responseStatus>
+  <vserverStatus>STOPPED</vserverStatus>
+</GetVServerStatusResponse>
\ No newline at end of file
diff --git a/labs/fgcp/src/test/resources/responses/ListDiskImage-response.xml b/labs/fgcp/src/test/resources/responses/ListDiskImage-response.xml
new file mode 100644
index 0000000..765979a
--- /dev/null
+++ b/labs/fgcp/src/test/resources/responses/ListDiskImage-response.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ListDiskImageResponse xmlns="http://apioviss.jp.fujitsu.com">
+  <diskimages>
+    <diskimage>
+      <creatorName>ABCDEFGH</creatorName>
+      <description />
+      <diskimageId>IMG_A1B2C3_1234567890ABCD</diskimageId>
+      <diskimageName>CentOS 6.0 64bit(EN)</diskimageName>
+      <licenseInfo />
+      <osName>CentOS 6.0 64bit (English)</osName>
+      <osType>pv</osType>
+      <registrant>ABCDEFGH</registrant>
+      <size>10.0</size>
+    </diskimage>
+  </diskimages>
+  <responseMessage>Processing was completed.</responseMessage>
+  <responseStatus>SUCCESS</responseStatus>
+</ListDiskImageResponse>
\ No newline at end of file
diff --git a/labs/fgcp/src/test/resources/responses/ListDiskImages-response.xml b/labs/fgcp/src/test/resources/responses/ListDiskImages-response.xml
new file mode 100644
index 0000000..c7f0e83
--- /dev/null
+++ b/labs/fgcp/src/test/resources/responses/ListDiskImages-response.xml
@@ -0,0 +1,118 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ListDiskImageResponse xmlns="http://apioviss.jp.fujitsu.com">
+  <diskimages>
+    <diskimage>
+      <creatorName>ABCDEFGH</creatorName>
+      <description />
+      <diskimageId>IMG_A1B2C3_1234567890ABCA</diskimageId>
+      <diskimageName />
+      <licenseInfo>Included</licenseInfo>
+      <osName>Windows Server 2008 R2 EE 64bit (English)</osName>
+      <osType>hvm</osType>
+      <registrant>ABCDEFGH</registrant>
+      <size>40.0</size>
+    </diskimage>
+    <diskimage>
+      <creatorName>ABCDEFGH</creatorName>
+      <description />
+      <diskimageId>IMG_A1B2C3_1234567890ABCB</diskimageId>
+      <diskimageName>my image</diskimageName>
+      <licenseInfo />
+      <osName>CentOS 6.2 64bit (English)</osName>
+      <osType>pv</osType>
+      <registrant>ABCDEFGH</registrant>
+      <size>10.0</size>
+    </diskimage>
+    <diskimage>
+      <creatorName>ABCDEFGH</creatorName>
+      <description />
+      <diskimageId>IMG_A1B2C3_1234567890ABCC</diskimageId>
+      <diskimageName>W2k8R2EE(EN)</diskimageName>
+      <licenseInfo>Included</licenseInfo>
+      <osName>Windows Server 2008 R2 EE 64bit (English)</osName>
+      <osType>hvm</osType>
+      <registrant>ABCDEFGH</registrant>
+      <size>40.0</size>
+    </diskimage>
+    <diskimage>
+      <creatorName>ABCDEFGH</creatorName>
+      <description />
+      <diskimageId>IMG_A1B2C3_1234567890ABCD</diskimageId>
+      <diskimageName>CentOS 5.6 64bit(EN)</diskimageName>
+      <licenseInfo />
+      <osName>CentOS 5.6 64bit (English)</osName>
+      <osType>pv</osType>
+      <registrant>ABCDEFGH</registrant>
+      <size>10.0</size>
+    </diskimage>
+    <diskimage>
+      <creatorName>ABCDEFGH</creatorName>
+      <description />
+      <diskimageId>IMG_A1B2C3_1234567890ABCE</diskimageId>
+      <diskimageName>W2k8R2SE/SQL2k8R2(EN)</diskimageName>
+      <licenseInfo>Included</licenseInfo>
+      <osName>Windows Server 2008 R2 SE 64bit (English)</osName>
+      <osType>hvm</osType>
+      <registrant>ABCDEFGH</registrant>
+      <size>40.0</size>
+      <softwares>
+        <software>
+          <license>Included</license>
+          <name>SQLServer 2008 R2 SE (English)</name>
+        </software>
+      </softwares>
+    </diskimage>
+    <diskimage>
+      <creatorName>ABCDEFGH</creatorName>
+      <description />
+      <diskimageId>IMG_A1B2C3_1234567890ABCF</diskimageId>
+      <diskimageName>W2k8R2SE(EN)</diskimageName>
+      <licenseInfo>Included</licenseInfo>
+      <osName>Windows Server 2008 R2 SE 64bit (English)</osName>
+      <osType>hvm</osType>
+      <registrant>ABCDEFGH</registrant>
+      <size>40.0</size>
+    </diskimage>
+    <diskimage>
+      <creatorName>ABCDEFGH</creatorName>
+      <description />
+      <diskimageId>IMG_A1B2C3_1234567890ABCG</diskimageId>
+      <diskimageName>CentOS 6.0 64bit(EN)</diskimageName>
+      <licenseInfo />
+      <osName>CentOS 6.0 64bit (English)</osName>
+      <osType>pv</osType>
+      <registrant>ABCDEFGH</registrant>
+      <size>10.0</size>
+    </diskimage>
+    <diskimage>
+      <creatorName>ABCDEFGH</creatorName>
+      <description />
+      <diskimageId>IMG_A1B2C3_1234567890ABCH</diskimageId>
+      <diskimageName>CentOS 6.0 32bit(EN)</diskimageName>
+      <licenseInfo />
+      <osName>CentOS 6.0 32bit (English)</osName>
+      <osType>pv</osType>
+      <registrant>ABCDEFGH</registrant>
+      <size>10.0</size>
+    </diskimage>
+    <diskimage>
+      <creatorName>ABCDEFGH</creatorName>
+      <description />
+      <diskimageId>IMG_A1B2C3_1234567890ABCI</diskimageId>
+      <diskimageName>W2k8R2SE/IIS(EN)</diskimageName>
+      <licenseInfo>Included</licenseInfo>
+      <osName>Windows Server 2008 R2 SE 64bit (English)</osName>
+      <osType>hvm</osType>
+      <registrant>ABCDEFGH</registrant>
+      <size>40.0</size>
+      <softwares>
+        <software>
+          <license />
+          <name>Internet Information Server 7.5</name>
+        </software>
+      </softwares>
+    </diskimage>
+  </diskimages>
+  <responseMessage>Processing was completed.</responseMessage>
+  <responseStatus>SUCCESS</responseStatus>
+</ListDiskImageResponse>
\ No newline at end of file
diff --git a/labs/fgcp/src/test/resources/responses/ListEFM-response.xml b/labs/fgcp/src/test/resources/responses/ListEFM-response.xml
new file mode 100644
index 0000000..3e4a1e3
--- /dev/null
+++ b/labs/fgcp/src/test/resources/responses/ListEFM-response.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ListEFMResponse xmlns="http://apioviss.jp.fujitsu.com">
+  <efms>
+    <efm>
+      <creator>ABCDEFGH</creator>
+      <efmId>ABCDEFGH-A123B456CE-S-0001</efmId>
+      <efmName>Firewall</efmName>
+      <efmType>FW</efmType>
+    </efm>
+  </efms>
+  <responseMessage>Processing was completed.</responseMessage>
+  <responseStatus>SUCCESS</responseStatus>
+</ListEFMResponse>
diff --git a/labs/fgcp/src/test/resources/responses/ListEFMBackup-response.xml b/labs/fgcp/src/test/resources/responses/ListEFMBackup-response.xml
new file mode 100644
index 0000000..780dbed
--- /dev/null
+++ b/labs/fgcp/src/test/resources/responses/ListEFMBackup-response.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ListEFMBackupResponse xmlns="http://apioviss.jp.fujitsu.com">
+  <backups>
+    <backup>
+      <backupId>001</backupId>
+      <backupTime>20121008201127</backupTime>
+    </backup>
+    <backup>
+      <backupId>002</backupId>
+      <backupTime>20121009201127</backupTime>
+    </backup>
+  </backups>
+  <responseMessage>Processing was completed.</responseMessage>
+  <responseStatus>SUCCESS</responseStatus>
+</ListEFMBackupResponse>
diff --git a/labs/fgcp/src/test/resources/responses/ListPublicIP-response.xml b/labs/fgcp/src/test/resources/responses/ListPublicIP-response.xml
new file mode 100644
index 0000000..6286209
--- /dev/null
+++ b/labs/fgcp/src/test/resources/responses/ListPublicIP-response.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ListPublicIPResponse xmlns="http://apioviss.jp.fujitsu.com">
+    <publicips>
+        <publicip>
+            <address>123.45.67.89</address>
+            <v4v6Flag>IPv4</v4v6Flag>
+            <vsysId>ABCDEFGH-A123B456CE</vsysId>
+        </publicip>
+        <publicip>
+            <address>123.45.67.90</address>
+            <v4v6Flag>IPv4</v4v6Flag>
+            <vsysId>ABCDEFGH-A123B456CD</vsysId>
+        </publicip>
+    </publicips>
+    <responseMessage>Processing was completed.</responseMessage>
+    <responseStatus>SUCCESS</responseStatus>
+</ListPublicIPResponse>
diff --git a/labs/fgcp/src/test/resources/responses/ListPublicIP_one_vsys-response.xml b/labs/fgcp/src/test/resources/responses/ListPublicIP_one_vsys-response.xml
new file mode 100644
index 0000000..d470837
--- /dev/null
+++ b/labs/fgcp/src/test/resources/responses/ListPublicIP_one_vsys-response.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ListPublicIPResponse xmlns="http://apioviss.jp.fujitsu.com">
+    <publicips>
+        <publicip>
+            <address>123.45.67.88</address>
+            <v4v6Flag>IPv4</v4v6Flag>
+            <vsysId>ABCDEFGH-A123B456CE</vsysId>
+        </publicip>
+        <publicip>
+            <address>123.45.67.89</address>
+            <v4v6Flag>IPv4</v4v6Flag>
+            <vsysId>ABCDEFGH-A123B456CE</vsysId>
+        </publicip>
+    </publicips>
+    <responseMessage>Processing was completed.</responseMessage>
+    <responseStatus>SUCCESS</responseStatus>
+</ListPublicIPResponse>
diff --git a/labs/fgcp/src/test/resources/responses/ListServerType-response.xml b/labs/fgcp/src/test/resources/responses/ListServerType-response.xml
new file mode 100644
index 0000000..0c9cee6
--- /dev/null
+++ b/labs/fgcp/src/test/resources/responses/ListServerType-response.xml
@@ -0,0 +1,82 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ListServerTypeResponse xmlns="http://apioviss.jp.fujitsu.com">
+    <responseMessage>Processing was completed.</responseMessage>
+    <responseStatus>SUCCESS</responseStatus>
+    <servertypes>
+        <servertype>
+            <chargeType>amount</chargeType>
+            <cpu>
+                <cpuArch>IA</cpuArch>
+                <cpuPerf>4.0</cpuPerf>
+                <numOfCpu>1</numOfCpu>
+            </cpu>
+            <expectedUsage>744</expectedUsage>
+            <id>islanda-cbrm_144</id>
+            <memory>
+                <memorySize>7.5</memorySize>
+            </memory>
+            <name>advanced</name>
+            <price>0.3</price>
+            <productId>AUS-VM-0001-0003</productId>
+            <productName>Advanced VM</productName>
+        </servertype>
+        <servertype>
+            <chargeType>amount</chargeType>
+            <cpu>
+                <cpuArch>IA</cpuArch>
+                <cpuPerf>1.0</cpuPerf>
+                <numOfCpu>1</numOfCpu>
+            </cpu>
+            <expectedUsage>744</expectedUsage>
+            <id>islanda-cbrm_140</id>
+            <memory>
+                <memorySize>1.7</memorySize>
+            </memory>
+            <name>economy</name>
+            <price>0.1</price>
+            <productId>AUS-VM-0001-0001</productId>
+            <productName>Economy VM</productName>
+        </servertype>
+        <servertype>
+            <chargeType>amount</chargeType>
+            <cpu>
+                <cpuArch>IA</cpuArch>
+                <cpuPerf>4.0</cpuPerf>
+                <numOfCpu>2</numOfCpu>
+            </cpu>
+            <expectedUsage>744</expectedUsage>
+            <id>islanda-cbrm_146</id>
+            <memory>
+                <memorySize>15.0</memorySize>
+            </memory>
+            <name>high_performance</name>
+            <price>0.4</price>
+            <productId>AUS-VM-0001-0004</productId>
+            <productName>High-Performance VM</productName>
+        </servertype>
+        <servertype>
+            <chargeType>amount</chargeType>
+            <cpu>
+                <cpuArch>IA</cpuArch>
+                <cpuPerf>2.0</cpuPerf>
+                <numOfCpu>1</numOfCpu>
+            </cpu>
+            <disks>
+                <disk>
+                    <diskSize>10</diskSize>
+                    <diskType>Disk type</diskType>
+                    <diskUsage>Disk purpose</diskUsage>
+                </disk>
+            </disks>
+            <expectedUsage>744</expectedUsage>
+            <id>islanda-cbrm_142</id>
+            <memory>
+                <memorySize>3.4</memorySize>
+            </memory>
+            <name>standard</name>
+            <price>0.3</price>
+            <productId>AUS-VM-0001-0002</productId>
+            <productName>Standard VM</productName>
+        </servertype>
+    </servertypes>
+</ListServerTypeResponse>
\ No newline at end of file
diff --git a/labs/fgcp/src/test/resources/responses/ListVDisk-response.xml b/labs/fgcp/src/test/resources/responses/ListVDisk-response.xml
new file mode 100644
index 0000000..e9e9242
--- /dev/null
+++ b/labs/fgcp/src/test/resources/responses/ListVDisk-response.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ListVDiskResponse xmlns="http://apioviss.jp.fujitsu.com">
+  <responseMessage>Processing was completed.</responseMessage>
+  <responseStatus>SUCCESS</responseStatus>
+  <vdisks>
+    <vdisk>
+      <attachedTo>ABCDEFGH-A123B456CE-S-0006</attachedTo>
+      <creator>ABCDEFGH</creator>
+      <size>10.0</size>
+      <vdiskId>ABCDEFGH-A123B456CE-S-0006</vdiskId>
+      <vdiskName>VM1</vdiskName>
+    </vdisk>
+  </vdisks>
+</ListVDiskResponse>
\ No newline at end of file
diff --git a/labs/fgcp/src/test/resources/responses/ListVSYS-response.xml b/labs/fgcp/src/test/resources/responses/ListVSYS-response.xml
new file mode 100644
index 0000000..947f787
--- /dev/null
+++ b/labs/fgcp/src/test/resources/responses/ListVSYS-response.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ListVSYSResponse xmlns="http://apioviss.jp.fujitsu.com">
+    <responseMessage>Processing was completed.</responseMessage>
+    <responseStatus>SUCCESS</responseStatus>
+    <vsyss>
+        <vsys>
+            <baseDescriptor>2-tier Skeleton</baseDescriptor>
+            <creator>ABCDEFGH</creator>
+            <description>2-tier Skeleton</description>
+            <vsysId>ABCDEFGH-I123J456K</vsysId>
+            <vsysName>expect test</vsysName>
+        </vsys>
+        <vsys>
+            <baseDescriptor>2-tier Skeleton</baseDescriptor>
+            <creator>ABCDEFGH</creator>
+            <description>2-tier Skeleton</description>
+            <vsysId>ABCDEFGH-L654J321I</vsysId>
+            <vsysName>expect test 2</vsysName>
+        </vsys>
+    </vsyss>
+</ListVSYSResponse>
\ No newline at end of file
diff --git a/labs/fgcp/src/test/resources/responses/ListVServer-response.xml b/labs/fgcp/src/test/resources/responses/ListVServer-response.xml
new file mode 100644
index 0000000..643925d
--- /dev/null
+++ b/labs/fgcp/src/test/resources/responses/ListVServer-response.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ListVServerResponse xmlns="http://apioviss.jp.fujitsu.com">
+  <responseMessage>Processing was completed.</responseMessage>
+  <responseStatus>SUCCESS</responseStatus>
+  <vservers>
+    <vserver>
+      <creator>ABCDEFGH</creator>
+      <diskimageId>IMG_A1B2C3_1234567890ABCD</diskimageId>
+      <vserverId>ABCDEFGH-A123B456CE-S-0005</vserverId>
+      <vserverName>VM1</vserverName>
+      <vserverType>economy</vserverType>
+    </vserver>
+    <vserver>
+      <creator>ABCDEFGH</creator>
+      <diskimageId>IMG_A1B2C3_1234567890ABCD</diskimageId>
+      <vserverId>ABCDEFGH-A123B456CE-S-0006</vserverId>
+      <vserverName>VM2</vserverName>
+      <vserverType>standard</vserverType>
+    </vserver>
+  </vservers>
+</ListVServerResponse>
diff --git a/labs/fgcp/src/test/resources/responses/RestoreEFM-response.xml b/labs/fgcp/src/test/resources/responses/RestoreEFM-response.xml
new file mode 100644
index 0000000..03a9871
--- /dev/null
+++ b/labs/fgcp/src/test/resources/responses/RestoreEFM-response.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<RestoreEFMResponse xmlns="http://apioviss.jp.fujitsu.com">
+  <responseMessage>Processing was completed.</responseMessage>
+  <responseStatus>SUCCESS</responseStatus>
+</RestoreEFMResponse>
\ No newline at end of file
diff --git a/labs/fgcp/src/test/resources/responses/RestoreVDisk-response.xml b/labs/fgcp/src/test/resources/responses/RestoreVDisk-response.xml
new file mode 100644
index 0000000..a4f4bd7
--- /dev/null
+++ b/labs/fgcp/src/test/resources/responses/RestoreVDisk-response.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<RestoreVDiskResponse xmlns="http://apioviss.jp.fujitsu.com">
+  <responseMessage>Processing was completed.</responseMessage>
+  <responseStatus>SUCCESS</responseStatus>
+</RestoreVDiskResponse>
\ No newline at end of file
diff --git a/labs/fgcp/src/test/resources/responses/StartEFM-response.xml b/labs/fgcp/src/test/resources/responses/StartEFM-response.xml
new file mode 100644
index 0000000..1914e55
--- /dev/null
+++ b/labs/fgcp/src/test/resources/responses/StartEFM-response.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<StartEFMResponse xmlns="http://apioviss.jp.fujitsu.com">
+  <responseMessage>Processing was completed.</responseMessage>
+  <responseStatus>SUCCESS</responseStatus>
+</StartEFMResponse>
\ No newline at end of file
diff --git a/labs/fgcp/src/test/resources/responses/StartVServer-response.xml b/labs/fgcp/src/test/resources/responses/StartVServer-response.xml
new file mode 100644
index 0000000..0648bb7
--- /dev/null
+++ b/labs/fgcp/src/test/resources/responses/StartVServer-response.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<StartVServerResponse xmlns="http://apioviss.jp.fujitsu.com">
+  <responseMessage>Processing was completed.</responseMessage>
+  <responseStatus>SUCCESS</responseStatus>
+</StartVServerResponse>
\ No newline at end of file
diff --git a/labs/fgcp/src/test/resources/responses/StopEFM-response.xml b/labs/fgcp/src/test/resources/responses/StopEFM-response.xml
new file mode 100644
index 0000000..332d315
--- /dev/null
+++ b/labs/fgcp/src/test/resources/responses/StopEFM-response.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<StopVServerResponse xmlns="http://apioviss.jp.fujitsu.com">
+  <responseMessage>Processing was completed.</responseMessage>
+  <responseStatus>SUCCESS</responseStatus>
+</StopVServerResponse>
\ No newline at end of file
diff --git a/labs/fgcp/src/test/resources/responses/StopVServer-response.xml b/labs/fgcp/src/test/resources/responses/StopVServer-response.xml
new file mode 100644
index 0000000..332d315
--- /dev/null
+++ b/labs/fgcp/src/test/resources/responses/StopVServer-response.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<StopVServerResponse xmlns="http://apioviss.jp.fujitsu.com">
+  <responseMessage>Processing was completed.</responseMessage>
+  <responseStatus>SUCCESS</responseStatus>
+</StopVServerResponse>
\ No newline at end of file
diff --git a/labs/fgcp/src/test/resources/responses/UnregisterDiskImage-response.xml b/labs/fgcp/src/test/resources/responses/UnregisterDiskImage-response.xml
new file mode 100644
index 0000000..65d4052
--- /dev/null
+++ b/labs/fgcp/src/test/resources/responses/UnregisterDiskImage-response.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<UnregisterDiskImageResponse xmlns="http://apioviss.jp.fujitsu.com">
+  <responseMessage>Processing was completed.</responseMessage>
+  <responseStatus>SUCCESS</responseStatus>
+</UnregisterDiskImageResponse>
\ No newline at end of file
diff --git a/labs/fgcp/src/test/resources/responses/UnregisterPrivateVSYSDescriptor-response.xml b/labs/fgcp/src/test/resources/responses/UnregisterPrivateVSYSDescriptor-response.xml
new file mode 100644
index 0000000..fcb6dce
--- /dev/null
+++ b/labs/fgcp/src/test/resources/responses/UnregisterPrivateVSYSDescriptor-response.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<UnregisterPrivateVSYSDescriptorResponse xmlns="http://apioviss.jp.fujitsu.com">
+  <responseMessage>Processing was completed.</responseMessage>
+  <responseStatus>SUCCESS</responseStatus>
+</UnregisterPrivateVSYSDescriptorResponse>
\ No newline at end of file
diff --git a/labs/fgcp/src/test/resources/responses/UnregisterVSYSDescriptor-response.xml b/labs/fgcp/src/test/resources/responses/UnregisterVSYSDescriptor-response.xml
new file mode 100644
index 0000000..884e5fd
--- /dev/null
+++ b/labs/fgcp/src/test/resources/responses/UnregisterVSYSDescriptor-response.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<UnregisterVSYSDescriptorResponse xmlns="http://apioviss.jp.fujitsu.com">
+  <responseMessage>Processing was completed.</responseMessage>
+  <responseStatus>SUCCESS</responseStatus>
+</UnregisterVSYSDescriptorResponse>
\ No newline at end of file
diff --git a/labs/fgcp/src/test/resources/responses/UpdateDiskImageAttribute-response.xml b/labs/fgcp/src/test/resources/responses/UpdateDiskImageAttribute-response.xml
new file mode 100644
index 0000000..5210fc8
--- /dev/null
+++ b/labs/fgcp/src/test/resources/responses/UpdateDiskImageAttribute-response.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<UpdateDiskImageAttributeResponse xmlns="http://apioviss.jp.fujitsu.com">
+  <responseMessage>Processing was completed.</responseMessage>
+  <responseStatus>SUCCESS</responseStatus>
+</UpdateDiskImageAttributeResponse>
\ No newline at end of file
diff --git a/labs/fgcp/src/test/resources/responses/UpdateEFMAttribute-response.xml b/labs/fgcp/src/test/resources/responses/UpdateEFMAttribute-response.xml
new file mode 100644
index 0000000..935b9a2
--- /dev/null
+++ b/labs/fgcp/src/test/resources/responses/UpdateEFMAttribute-response.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<UpdateEFMAttributeResponse xmlns="http://apioviss.jp.fujitsu.com">
+  <responseMessage>Processing was completed.</responseMessage>
+  <responseStatus>SUCCESS</responseStatus>
+</UpdateEFMAttributeResponse>
\ No newline at end of file
diff --git a/labs/fgcp/src/test/resources/responses/UpdateVDiskAttribute-response.xml b/labs/fgcp/src/test/resources/responses/UpdateVDiskAttribute-response.xml
new file mode 100644
index 0000000..57ad948
--- /dev/null
+++ b/labs/fgcp/src/test/resources/responses/UpdateVDiskAttribute-response.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<UpdateVDiskAttributeResponse xmlns="http://apioviss.jp.fujitsu.com">
+  <responseMessage>Processing was completed.</responseMessage>
+  <responseStatus>SUCCESS</responseStatus>
+</UpdateVDiskAttributeResponse>
\ No newline at end of file
diff --git a/labs/fgcp/src/test/resources/responses/UpdateVSYSDescriptorAttribute-response.xml b/labs/fgcp/src/test/resources/responses/UpdateVSYSDescriptorAttribute-response.xml
new file mode 100644
index 0000000..d660bee
--- /dev/null
+++ b/labs/fgcp/src/test/resources/responses/UpdateVSYSDescriptorAttribute-response.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<UpdateVSYSDescriptorAttribute xmlns="http://apioviss.jp.fujitsu.com">
+  <responseMessage>Processing was completed.</responseMessage>
+  <responseStatus>SUCCESS</responseStatus>
+</UpdateVSYSDescriptorAttribute>
\ No newline at end of file
diff --git a/labs/fgcp/src/test/resources/responses/UpdateVServerAttribute-response.xml b/labs/fgcp/src/test/resources/responses/UpdateVServerAttribute-response.xml
new file mode 100644
index 0000000..b1be001
--- /dev/null
+++ b/labs/fgcp/src/test/resources/responses/UpdateVServerAttribute-response.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<UpdateVServerAttributeResponse xmlns="http://apioviss.jp.fujitsu.com">
+  <responseMessage>Processing was completed.</responseMessage>
+  <responseStatus>SUCCESS</responseStatus>
+</UpdateVServerAttributeResponse>
\ No newline at end of file
diff --git a/labs/nodepool/src/test/java/org/jclouds/nodepool/NodePoolComputeServiceLiveTest.java b/labs/nodepool/src/test/java/org/jclouds/nodepool/NodePoolComputeServiceLiveTest.java
index 7f8d320..9967252 100644
--- a/labs/nodepool/src/test/java/org/jclouds/nodepool/NodePoolComputeServiceLiveTest.java
+++ b/labs/nodepool/src/test/java/org/jclouds/nodepool/NodePoolComputeServiceLiveTest.java
@@ -19,17 +19,8 @@
 
 package org.jclouds.nodepool;
 
-import static com.google.common.collect.Iterables.getOnlyElement;
-import static java.lang.String.format;
-import static java.util.logging.Logger.getAnonymousLogger;
-import static org.jclouds.compute.RunScriptData.JBOSS_HOME;
-import static org.jclouds.compute.RunScriptData.installAdminUserJBossAndOpenPorts;
-import static org.jclouds.compute.RunScriptData.startJBoss;
 import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_PORT_OPEN;
 import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_SCRIPT_COMPLETE;
-import static org.jclouds.compute.options.RunScriptOptions.Builder.nameTask;
-import static org.jclouds.compute.options.TemplateOptions.Builder.inboundPorts;
-import static org.jclouds.compute.options.TemplateOptions.Builder.runAsRoot;
 import static org.jclouds.nodepool.config.NodePoolProperties.BASEDIR;
 import static org.jclouds.nodepool.config.NodePoolProperties.MAX_SIZE;
 import static org.jclouds.nodepool.config.NodePoolProperties.MIN_SIZE;
@@ -41,12 +32,8 @@
 
 import java.util.NoSuchElementException;
 import java.util.Properties;
-import java.util.concurrent.Callable;
-import java.util.concurrent.TimeUnit;
 
 import org.jclouds.compute.RunNodesException;
-import org.jclouds.compute.RunScriptData;
-import org.jclouds.compute.domain.ExecResponse;
 import org.jclouds.compute.domain.NodeMetadata;
 import org.jclouds.compute.internal.BaseComputeServiceLiveTest;
 import org.jclouds.compute.predicates.NodePredicates;
@@ -54,13 +41,9 @@
 import org.jclouds.logging.slf4j.config.SLF4JLoggingModule;
 import org.jclouds.rest.AuthorizationException;
 import org.jclouds.sshj.config.SshjSshClientModule;
-import org.jclouds.util.Strings2;
 import org.testng.annotations.AfterClass;
 import org.testng.annotations.Test;
 
-import com.google.common.base.Stopwatch;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.Iterables;
 import com.google.common.collect.Sets;
 import com.google.common.io.Closeables;
@@ -108,74 +91,7 @@
    @Override
    @Test(enabled = true, groups = "live")
    public void testCreateAndRunAService() throws Exception {
-      final String configuration = Strings2.toStringAndClose(RunScriptData.class
-               .getResourceAsStream("/standalone-basic.xml"));
-
-      ImmutableMap<String, String> userMetadata = ImmutableMap.<String, String> of("Name", group);
-      ImmutableSet<String> tags = ImmutableSet.of(group);
-      Stopwatch watch = new Stopwatch().start();
-      NodeMetadata node = getOnlyElement(client.createNodesInGroup(group, 1, inboundPorts(22, 8080)
-               .blockOnPort(22, 300).userMetadata(userMetadata).tags(tags)));
-      long createSeconds = watch.elapsedTime(TimeUnit.SECONDS);
-
-      final String nodeId = node.getId();
-
-      checkUserMetadataInNodeEquals(node, userMetadata);
-      checkTagsInNodeEquals(node, tags);
-
-      getAnonymousLogger().info(
-               format("<< available node(%s) os(%s) in %ss", node.getId(), node.getOperatingSystem(), createSeconds));
-
-      watch.reset().start();
-
-      // note this is a dependency on the template resolution so we have the
-      // right process per
-      // operating system. moreover, we wish this to run as root, so that it
-      // can change ip
-      // tables rules and setup our admin user
-      client.runScriptOnNode(nodeId, installAdminUserJBossAndOpenPorts(node.getOperatingSystem()),
-               nameTask("configure-jboss"));
-
-      long configureSeconds = watch.elapsedTime(TimeUnit.SECONDS);
-
-      getAnonymousLogger()
-               .info(format("<< configured node(%s) with %s and JBoss %s in %ss",
-                        nodeId,
-                        exec(nodeId, "java -fullversion"),
-                        // version of the jboss jar
-                        exec(nodeId,
-                                 format("ls %s/bundles/org/jboss/as/osgi/configadmin/main|sed -e 's/.*-//g' -e 's/.jar//g'",
-                                          JBOSS_HOME)), configureSeconds));
-
-      trackAvailabilityOfProcessOnNode(view.utils().userExecutor().submit(new Callable<ExecResponse>() {
-         @Override
-         public ExecResponse call() {
-            return client.runScriptOnNode(nodeId, startJBoss(configuration), runAsRoot(false).blockOnComplete(false)
-                     .nameTask("jboss"));
-         }
-
-         @Override
-         public String toString() {
-            return "initial start of jboss";
-         }
-
-      }), "jboss", node, JBOSS_PATTERN);
-
-      client.runScriptOnNode(nodeId, "/tmp/init-jboss stop", runAsRoot(false).wrapInInitScript(false));
-
-      trackAvailabilityOfProcessOnNode(view.utils().userExecutor().submit(new Callable<ExecResponse>() {
-
-         @Override
-         public ExecResponse call() {
-            return client.runScriptOnNode(nodeId, "/tmp/init-jboss start", runAsRoot(false).wrapInInitScript(false));
-         }
-
-         @Override
-         public String toString() {
-            return "warm start of jboss";
-         }
-
-      }), "jboss", node, JBOSS_PATTERN);
+      createAndRunAServiceInGroup(group);
    }
 
    @Test(enabled = true, groups = "live", dependsOnMethods = "testCreateAndRunAService")
diff --git a/labs/pom.xml b/labs/pom.xml
index 7d08d58..0ddb6ed 100644
--- a/labs/pom.xml
+++ b/labs/pom.xml
@@ -57,5 +57,9 @@
        <module>aws-rds</module>
        <module>smartos-ssh</module>
        <module>cloudstack-ec2</module>
+       <module>azure-management</module>
+       <module>fgcp</module>
+       <module>fgcp-au</module>
+       <module>fgcp-de</module>
     </modules>
 </project>
diff --git a/labs/vcloud-director/src/main/java/org/jclouds/vcloud/director/v1_5/binders/BindMapAsMetadata.java b/labs/vcloud-director/src/main/java/org/jclouds/vcloud/director/v1_5/binders/BindMapAsMetadata.java
new file mode 100644
index 0000000..549f41a
--- /dev/null
+++ b/labs/vcloud-director/src/main/java/org/jclouds/vcloud/director/v1_5/binders/BindMapAsMetadata.java
@@ -0,0 +1,49 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.vcloud.director.v1_5.binders;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.util.Map;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+import org.jclouds.http.HttpRequest;
+import org.jclouds.rest.binders.BindToXMLPayload;
+import org.jclouds.vcloud.director.v1_5.domain.Metadata;
+import org.jclouds.xml.XMLParser;
+
+/**
+ * Changes a Map to the crufty {@link Metadata type}
+ */
+@Singleton
+public class BindMapAsMetadata extends BindToXMLPayload {
+
+   @Inject
+   public BindMapAsMetadata(final XMLParser xmlParser) {
+      super(xmlParser);
+   }
+
+   @SuppressWarnings("unchecked")
+   @Override
+   public <R extends HttpRequest> R bindToRequest(final R request, final Object input) {
+      return super.bindToRequest(request, Metadata.toMetadata(Map.class.cast(checkNotNull(input, "input"))));
+   }
+}
diff --git a/labs/vcloud-director/src/main/java/org/jclouds/vcloud/director/v1_5/binders/BindStringAsMetadataValue.java b/labs/vcloud-director/src/main/java/org/jclouds/vcloud/director/v1_5/binders/BindStringAsMetadataValue.java
new file mode 100644
index 0000000..4f1d489
--- /dev/null
+++ b/labs/vcloud-director/src/main/java/org/jclouds/vcloud/director/v1_5/binders/BindStringAsMetadataValue.java
@@ -0,0 +1,66 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.vcloud.director.v1_5.binders;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+
+import org.jclouds.http.HttpRequest;
+import org.jclouds.rest.binders.BindToXMLPayload;
+import org.jclouds.vcloud.director.v1_5.VCloudDirectorMediaType;
+import org.jclouds.vcloud.director.v1_5.domain.Resource;
+import org.jclouds.xml.XMLParser;
+
+/**
+ * Changes a String to the crufty {@link MetadataValue type}
+ */
+@Singleton
+public class BindStringAsMetadataValue extends BindToXMLPayload {
+   @XmlRootElement(name = "MetadataValue")
+   public static class MetadataValue extends Resource {
+      public static final String MEDIA_TYPE = VCloudDirectorMediaType.METADATA_VALUE;
+
+      public MetadataValue() {
+
+      }
+
+      public MetadataValue(String value) {
+         super(Resource.builder());
+         this.value = value;
+      }
+
+      @XmlElement(name = "Value", required = true)
+      private String value;
+
+   }
+
+   @Inject
+   public BindStringAsMetadataValue(final XMLParser xmlParser) {
+      super(xmlParser);
+   }
+
+   @Override
+   public <R extends HttpRequest> R bindToRequest(final R request, final Object input) {
+      return super.bindToRequest(request, new MetadataValue(checkNotNull(input, "input").toString()));
+   }
+}
diff --git a/labs/vcloud-director/src/main/java/org/jclouds/vcloud/director/v1_5/binders/package-info.java b/labs/vcloud-director/src/main/java/org/jclouds/vcloud/director/v1_5/binders/package-info.java
new file mode 100644
index 0000000..3aa81f6
--- /dev/null
+++ b/labs/vcloud-director/src/main/java/org/jclouds/vcloud/director/v1_5/binders/package-info.java
@@ -0,0 +1,35 @@
+/*
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+@XmlSchema(namespace = VCLOUD_1_5_NS,
+      elementFormDefault = XmlNsForm.QUALIFIED,
+      xmlns = {
+            @XmlNs(prefix = "", namespaceURI = VCLOUD_1_5_NS)
+      }
+)
+@XmlAccessorType(XmlAccessType.FIELD)
+package org.jclouds.vcloud.director.v1_5.binders;
+
+import static org.jclouds.vcloud.director.v1_5.VCloudDirectorConstants.VCLOUD_1_5_NS;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlNs;
+import javax.xml.bind.annotation.XmlNsForm;
+import javax.xml.bind.annotation.XmlSchema;
+
diff --git a/labs/vcloud-director/src/main/java/org/jclouds/vcloud/director/v1_5/domain/Metadata.java b/labs/vcloud-director/src/main/java/org/jclouds/vcloud/director/v1_5/domain/Metadata.java
index 266cd2b..fc7118e 100644
--- a/labs/vcloud-director/src/main/java/org/jclouds/vcloud/director/v1_5/domain/Metadata.java
+++ b/labs/vcloud-director/src/main/java/org/jclouds/vcloud/director/v1_5/domain/Metadata.java
@@ -48,6 +48,16 @@
  */
 @XmlRootElement(name = "Metadata")
 public class Metadata extends Resource implements Map<String, String> {
+   
+   public static Metadata toMetadata(Map<String, String> input) {
+      if (input instanceof Metadata)
+         return Metadata.class.cast(input);
+      Builder<?> builder = builder();
+      for (Map.Entry<String, String> entry : input.entrySet()) {
+         builder.entry(MetadataEntry.builder().entry(entry.getKey(), entry.getValue()).build());
+      }
+      return builder.build();
+   }
 
    public static final String MEDIA_TYPE = VCloudDirectorMediaType.METADATA;
 
@@ -66,7 +76,7 @@
    public static abstract class Builder<B extends Builder<B>> extends Resource.Builder<B> {
 
       private Set<MetadataEntry> metadataEntries = Sets.newLinkedHashSet();
-
+      
       /**
        * @see Metadata#getMetadataEntries()
        */
diff --git a/labs/vcloud-director/src/main/java/org/jclouds/vcloud/director/v1_5/domain/MetadataValue.java b/labs/vcloud-director/src/main/java/org/jclouds/vcloud/director/v1_5/domain/MetadataValue.java
index 6a69694..c7030b8 100644
--- a/labs/vcloud-director/src/main/java/org/jclouds/vcloud/director/v1_5/domain/MetadataValue.java
+++ b/labs/vcloud-director/src/main/java/org/jclouds/vcloud/director/v1_5/domain/MetadataValue.java
@@ -42,116 +42,3 @@
  *
  * @author grkvlt@apache.org
  */
-@XmlRootElement(name = "MetadataValue")
-public class MetadataValue extends Resource {
-
-   public static final String MEDIA_TYPE = VCloudDirectorMediaType.METADATA_ENTRY;
-
-   public static Builder<?> builder() {
-      return new ConcreteBuilder();
-   }
-
-   @Override
-   public Builder<?> toBuilder() {
-      return builder().fromMetadataValue(this);
-   }
-
-   private static class ConcreteBuilder extends Builder<ConcreteBuilder> {
-   }
-   
-   public static abstract class Builder<B extends Builder<B>> extends Resource.Builder<B> {
-      private String value;
-
-      /**
-       * @see MetadataValue#getValue
-       */
-      public B value(String value) {
-         this.value = value;
-         return self();
-      }
-
-      @Override
-      public MetadataValue build() {
-         return new MetadataValue(this);
-      }
-
-      /**
-       * @see ResourceType#getHref()
-       */
-      @Override
-      public B href(URI href) {
-         super.href(href);
-         return self();
-      }
-
-      /**
-       * @see ResourceType#getType()
-       */
-      @Override
-      public B type(String type) {
-         super.type(type);
-         return self();
-      }
-
-      /**
-       * @see ResourceType#getLinks()
-       */
-      @Override
-      public B links(Set<Link> links) {
-         super.links(Sets.newLinkedHashSet(checkNotNull(links, "links")));
-         return self();
-      }
-
-      /**
-       * @see ResourceType#getLinks()
-       */
-      @Override
-      public B link(Link link) {
-         super.link(link);
-         return self();
-      }
-
-      public B fromMetadataValue(MetadataValue in) {
-         return fromResource(in).value(value);
-      }
-   }
-
-   protected MetadataValue() {
-      // For JAXB
-   }
-
-   protected MetadataValue(Builder<?> builder) {
-      super(builder);
-      this.value = checkNotNull(builder.value, "value");
-   }
-
-   @XmlElement(name = "Value", required = true)
-   private String value;
-
-   /**
-    * The value.
-    */
-   public String getValue() {
-      return value;
-   }
-
-   @Override
-   public boolean equals(Object o) {
-      if (this == o)
-         return true;
-      if (o == null || getClass() != o.getClass())
-         return false;
-      MetadataValue that = MetadataValue.class.cast(o);
-      return super.equals(that) && equal(this.value, that.value);
-   }
-
-   @Override
-   public int hashCode() {
-      return Objects.hashCode(super.hashCode(), value);
-   }
-
-   @Override
-   public ToStringHelper string() {
-      return super.string().add("value", value);
-   }
-}
diff --git a/labs/vcloud-director/src/main/java/org/jclouds/vcloud/director/v1_5/features/MetadataApi.java b/labs/vcloud-director/src/main/java/org/jclouds/vcloud/director/v1_5/features/MetadataApi.java
index 18db889..fd9bb42 100644
--- a/labs/vcloud-director/src/main/java/org/jclouds/vcloud/director/v1_5/features/MetadataApi.java
+++ b/labs/vcloud-director/src/main/java/org/jclouds/vcloud/director/v1_5/features/MetadataApi.java
@@ -18,18 +18,18 @@
  */
 package org.jclouds.vcloud.director.v1_5.features;
 
+import java.util.Map;
 import java.util.concurrent.TimeUnit;
 
 import org.jclouds.concurrent.Timeout;
 import org.jclouds.vcloud.director.v1_5.domain.Metadata;
-import org.jclouds.vcloud.director.v1_5.domain.MetadataValue;
 import org.jclouds.vcloud.director.v1_5.domain.Task;
 
 /**
  * Provides synchronous access to {@link Metadata}.
  * 
  * @see MetadataAsyncApi
- * @author danikov
+ * @author danikov, Adrian Cole
  */
 public interface MetadataApi {
 
@@ -47,7 +47,7 @@
        * 
        * @return the metadata value, or null if not found
        */
-      MetadataValue getValue(String key);
+      String get(String key);
    }
 
    @Timeout(duration = 180, timeUnit = TimeUnit.SECONDS)
@@ -56,27 +56,30 @@
       /**
        * Merges the metadata for a media with the information provided.
        * 
-       * @return a task. This operation is asynchronous and the user should monitor the returned
-       *         task status in order to check when it is completed.
+       * @return a task. This operation is asynchronous and the user should
+       *         monitor the returned task status in order to check when it is
+       *         completed.
        */
-      Task merge(Metadata metadata);
+      Task putAll(Map<String, String> metadata);
 
       /**
-       * Sets the metadata for the particular key for the media to the value provided. Note: this
-       * will replace any existing metadata information
+       * Sets the metadata for the particular key for the media to the value
+       * provided. Note: this will replace any existing metadata information
        * 
-       * @return a task. This operation is asynchronous and the user should monitor the returned
-       *         task status in order to check when it is completed.
+       * @return a task. This operation is asynchronous and the user should
+       *         monitor the returned task status in order to check when it is
+       *         completed.
        */
-      Task putEntry(String key, MetadataValue metadataValue);
+      Task put(String key, String value);
 
       /**
        * Deletes a metadata entry.
        * 
-       * @return a task. This operation is asynchronous and the user should monitor the returned
-       *         task status in order to check when it is completed.
+       * @return a task. This operation is asynchronous and the user should
+       *         monitor the returned task status in order to check when it is
+       *         completed.
        */
-      Task removeEntry(String key);
+      Task remove(String key);
 
    }
 }
diff --git a/labs/vcloud-director/src/main/java/org/jclouds/vcloud/director/v1_5/features/MetadataAsyncApi.java b/labs/vcloud-director/src/main/java/org/jclouds/vcloud/director/v1_5/features/MetadataAsyncApi.java
index dcb9b1b..32f542c 100644
--- a/labs/vcloud-director/src/main/java/org/jclouds/vcloud/director/v1_5/features/MetadataAsyncApi.java
+++ b/labs/vcloud-director/src/main/java/org/jclouds/vcloud/director/v1_5/features/MetadataAsyncApi.java
@@ -18,7 +18,7 @@
  */
 package org.jclouds.vcloud.director.v1_5.features;
 
-import java.net.URI;
+import java.util.Map;
 
 import javax.ws.rs.Consumes;
 import javax.ws.rs.DELETE;
@@ -33,29 +33,29 @@
 import org.jclouds.rest.annotations.ExceptionParser;
 import org.jclouds.rest.annotations.JAXBResponseParser;
 import org.jclouds.rest.annotations.RequestFilters;
-import org.jclouds.rest.binders.BindToXMLPayload;
+import org.jclouds.rest.annotations.ResponseParser;
 import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404;
 import org.jclouds.vcloud.director.v1_5.VCloudDirectorMediaType;
+import org.jclouds.vcloud.director.v1_5.binders.BindMapAsMetadata;
+import org.jclouds.vcloud.director.v1_5.binders.BindStringAsMetadataValue;
 import org.jclouds.vcloud.director.v1_5.domain.Metadata;
-import org.jclouds.vcloud.director.v1_5.domain.MetadataEntry;
-import org.jclouds.vcloud.director.v1_5.domain.MetadataValue;
 import org.jclouds.vcloud.director.v1_5.domain.Task;
 import org.jclouds.vcloud.director.v1_5.filters.AddVCloudAuthorizationAndCookieToRequest;
+import org.jclouds.vcloud.director.v1_5.functions.RegexValueParser;
 
 import com.google.common.util.concurrent.ListenableFuture;
 
 /**
  * @see MetadataApi
- * @author danikov
+ * @author Adrian Cole, danikov
  */
-// TODO: take out the endpoint params and supply them in the Delegate calls.
 public interface MetadataAsyncApi {
 
    @RequestFilters(AddVCloudAuthorizationAndCookieToRequest.class)
    public static interface Readable extends MetadataAsyncApi {
 
       /**
-       * @see MetadataApi.Readable#get(URI)
+       * @see MetadataApi.Readable#get()
        */
       @GET
       @Path("/metadata")
@@ -65,14 +65,14 @@
       ListenableFuture<Metadata> get();
 
       /**
-       * @see MetadataApi.Readable#getValue(String)
+       * @see MetadataApi.Readable#get(String)
        */
       @GET
       @Path("/metadata/{key}")
       @Consumes
-      @JAXBResponseParser
+      @ResponseParser(RegexValueParser.class)
       @ExceptionParser(ReturnNullOnNotFoundOr404.class)
-      ListenableFuture<MetadataValue> getValue(@PathParam("key") String key);
+      ListenableFuture<String> get(@PathParam("key") String key);
 
    }
 
@@ -80,35 +80,34 @@
    public static interface Writeable extends Readable {
 
       /**
-       * @see MetadataApi.Writable#merge(Metadata)
+       * @see MetadataApi.Writable#putAll
        */
       @POST
       @Path("/metadata")
       @Consumes(VCloudDirectorMediaType.TASK)
       @Produces(VCloudDirectorMediaType.METADATA)
       @JAXBResponseParser
-      ListenableFuture<Task> merge(@BinderParam(BindToXMLPayload.class) Metadata metadata);
+      ListenableFuture<Task> putAll(@BinderParam(BindMapAsMetadata.class) Map<String, String> metadata);
 
       /**
-       * @see MetadataApi.Writeable#putEntry(String, MetadataEntry)
+       * @see MetadataApi.Writeable#put
        */
       @PUT
       @Path("/metadata/{key}")
       @Consumes(VCloudDirectorMediaType.TASK)
       @Produces(VCloudDirectorMediaType.METADATA_VALUE)
       @JAXBResponseParser
-      // TODO: this is rediculous. get rid of the MetadataValue type, as it is only a string!
-      ListenableFuture<Task> putEntry(@PathParam("key") String key,
-               @BinderParam(BindToXMLPayload.class) MetadataValue metadataValue);
+      ListenableFuture<Task> put(@PathParam("key") String key,
+            @BinderParam(BindStringAsMetadataValue.class) String metadataValue);
 
       /**
-       * @see MetadataApi.Writable#removeEntry(String)
+       * @see MetadataApi.Writable#remove
        */
       @DELETE
       @Path("/metadata/{key}")
       @Consumes(VCloudDirectorMediaType.TASK)
       @JAXBResponseParser
-      ListenableFuture<Task> removeEntry(@PathParam("key") String key);
+      ListenableFuture<Task> remove(@PathParam("key") String key);
 
    }
 }
diff --git a/labs/vcloud-director/src/main/java/org/jclouds/vcloud/director/v1_5/functions/RegexValueParser.java b/labs/vcloud-director/src/main/java/org/jclouds/vcloud/director/v1_5/functions/RegexValueParser.java
new file mode 100644
index 0000000..bb28395
--- /dev/null
+++ b/labs/vcloud-director/src/main/java/org/jclouds/vcloud/director/v1_5/functions/RegexValueParser.java
@@ -0,0 +1,58 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.vcloud.director.v1_5.functions;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import javax.inject.Inject;
+
+import org.jclouds.http.HttpResponse;
+import org.jclouds.http.functions.ReturnStringIf2xx;
+
+import com.google.common.base.Function;
+import com.google.inject.Singleton;
+
+/**
+ * 
+ * @author Adrian Cole
+ */
+@Singleton
+public class RegexValueParser implements Function<HttpResponse, String> {
+   Pattern pattern = Pattern.compile("<Value>([^<]+)</Value>");
+   private final ReturnStringIf2xx returnStringIf200;
+
+   @Inject
+   RegexValueParser(ReturnStringIf2xx returnStringIf200) {
+      this.returnStringIf200 = returnStringIf200;
+   }
+
+   @Override
+   public String apply(HttpResponse response) {
+      String content = returnStringIf200.apply(response);
+      if (content != null) {
+         Matcher matcher = pattern.matcher(content);
+         if (matcher.find()) {
+            return matcher.group(1);
+         }
+      }
+      return null;
+   }
+
+}
\ No newline at end of file
diff --git a/labs/vcloud-director/src/test/java/org/jclouds/vcloud/director/v1_5/AbstractVAppApiLiveTest.java b/labs/vcloud-director/src/test/java/org/jclouds/vcloud/director/v1_5/AbstractVAppApiLiveTest.java
index 1be4816..591daf6 100644
--- a/labs/vcloud-director/src/test/java/org/jclouds/vcloud/director/v1_5/AbstractVAppApiLiveTest.java
+++ b/labs/vcloud-director/src/test/java/org/jclouds/vcloud/director/v1_5/AbstractVAppApiLiveTest.java
@@ -50,6 +50,7 @@
 import org.jclouds.vcloud.director.v1_5.domain.dmtf.RasdItem;
 import org.jclouds.vcloud.director.v1_5.domain.network.NetworkConnection;
 import org.jclouds.vcloud.director.v1_5.domain.network.VAppNetworkConfiguration;
+import org.jclouds.vcloud.director.v1_5.domain.network.NetworkConnection.IpAddressAllocationMode;
 import org.jclouds.vcloud.director.v1_5.domain.params.UndeployVAppParams;
 import org.jclouds.vcloud.director.v1_5.domain.section.GuestCustomizationSection;
 import org.jclouds.vcloud.director.v1_5.domain.section.NetworkConnectionSection;
@@ -298,7 +299,7 @@
       Status status = test.getStatus();
       if (status != Status.POWERED_OFF || test.isDeployed()) {
          UndeployVAppParams undeployParams = UndeployVAppParams.builder().build();
-         Task shutdownVapp = vAppApi.undeploy(vmUrn, undeployParams);
+         Task shutdownVapp = vmApi.undeploy(vmUrn, undeployParams);
          assertTaskSucceedsLong(shutdownVapp);
       }
       test = vmApi.get(vmUrn);
@@ -396,4 +397,27 @@
       Set<VAppNetworkConfiguration> vAppNetworkConfigs = vAppApi.getNetworkConfigSection(vApp.getId()).getNetworkConfigs();
       return vAppNetworkConfigs;
    }
+   
+   protected void attachVmToVAppNetwork(Vm vm, String vAppNetworkName) {
+      Set<NetworkConnection> networkConnections = vmApi.getNetworkConnectionSection(vm.getId())
+               .getNetworkConnections();
+
+      NetworkConnectionSection section = NetworkConnectionSection.builder()
+               .info("info")
+               .primaryNetworkConnectionIndex(0)
+               .build();
+      
+      for (NetworkConnection networkConnection : networkConnections) {
+         NetworkConnection newNetworkConnection = networkConnection.toBuilder()
+                  .network(vAppNetworkName)
+                  .isConnected(true)
+                  .networkConnectionIndex(0)
+                  .ipAddressAllocationMode(IpAddressAllocationMode.POOL)
+                  .build();
+         
+         section = section.toBuilder().networkConnection(newNetworkConnection).build();
+      }
+      Task configureNetwork = vmApi.editNetworkConnectionSection(vm.getId(), section);
+      assertTaskSucceedsLong(configureNetwork);
+   } 
 }
diff --git a/labs/vcloud-director/src/test/java/org/jclouds/vcloud/director/v1_5/HttpClientLiveTest.java b/labs/vcloud-director/src/test/java/org/jclouds/vcloud/director/v1_5/HttpClientLiveTest.java
deleted file mode 100644
index 427db4a..0000000
--- a/labs/vcloud-director/src/test/java/org/jclouds/vcloud/director/v1_5/HttpClientLiveTest.java
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * Licensed to jclouds, Inc. (jclouds) under one or more
- * contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  jclouds licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.jclouds.vcloud.director.v1_5;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertNotNull;
-import static org.testng.Assert.assertTrue;
-
-import java.io.IOException;
-
-import org.jclouds.crypto.CryptoStreams;
-import org.jclouds.http.HttpRequest;
-import org.jclouds.http.HttpResponse;
-import org.jclouds.rest.HttpClient;
-import org.jclouds.util.Strings2;
-import org.jclouds.vcloud.director.v1_5.domain.SessionWithToken;
-import org.jclouds.vcloud.director.v1_5.domain.org.OrgList;
-import org.jclouds.vcloud.director.v1_5.internal.BaseVCloudDirectorApiLiveTest;
-import org.jclouds.xml.internal.JAXBParser;
-import org.testng.annotations.Test;
-
-import com.google.common.collect.Iterables;
-
-/**
- * Tests live behavior of operations that use {@link HttpClient}.
- * 
- * @author danikov
- */
-@Test(groups = { "live", "user" }, singleThreaded = true, testName = "HttpClientLiveTest")
-public class HttpClientLiveTest extends BaseVCloudDirectorApiLiveTest {
-
-   private JAXBParser parser = new JAXBParser("true");
-   private SessionWithToken sessionWithToken;
-
-   @Override
-   protected void setupRequiredApis() {
-   }
-
-   @Test(description = "POST /login")
-   public void testPostLogin() throws IOException {
-      testLoginWithMethod("POST");
-   }
-
-   @Test(description = "GET /login")
-   public void testGetLogin() throws IOException {
-      testLoginWithMethod("GET");
-   }
-
-   private void testLoginWithMethod(final String method) throws IOException {
-      String user = identity.substring(0, identity.lastIndexOf('@'));
-      String org = identity.substring(identity.lastIndexOf('@') + 1);
-      String password = credential;
-
-      String authHeader = "Basic " + CryptoStreams.base64(String.format("%s@%s:%s", checkNotNull(user), checkNotNull(org), checkNotNull(password)).getBytes("UTF-8"));
-
-      HttpResponse response = context.getUtils().getHttpClient().invoke(HttpRequest.builder()
-            .method(method)
-            .endpoint(endpoint + "/login")
-            .addHeader("Authorization", authHeader)
-            .addHeader("Accept", "*/*").build());
-
-      sessionWithToken = SessionWithToken.builder().session(session).token(response.getFirstHeaderOrNull("x-vcloud-authorization")).build();
-
-      assertEquals(sessionWithToken.getSession().getUser(), user);
-      assertEquals(sessionWithToken.getSession().get(), org);
-      assertTrue(sessionWithToken.getSession().getLinks().size() > 0);
-      assertNotNull(sessionWithToken.getToken());
-
-      OrgList orgList = parser.fromXML(Strings2.toString(response.getPayload()), OrgList.class);
-
-      assertTrue(orgList.size() > 0, "must have orgs");
-
-      context.getApi().getOrgApi().get(Iterables.getLast(orgList).getHref());
-   }
-
-   @Test(description = "GET /schema/{schemaFileName}", dependsOnMethods = { "testPostLogin", "testGetLogin" })
-   public void testGetSchema() throws IOException {
-      String schemafileName = "master.xsd";
-      HttpResponse response = context.getUtils().getHttpClient().invoke(HttpRequest.builder()
-            .method("GET")
-            .endpoint(endpoint + "/v1.5/schema/" + schemafileName)
-            .addHeader("x-vcloud-authorization", sessionWithToken.getToken())
-            .addHeader("Accept", "*/*").build());
-
-      String schema = Strings2.toString(response.getPayload());
-
-      // TODO: asserting something about the schema
-   }
-
-}
diff --git a/labs/vcloud-director/src/test/java/org/jclouds/vcloud/director/v1_5/binders/BindMapAsMetadataTest.java b/labs/vcloud-director/src/test/java/org/jclouds/vcloud/director/v1_5/binders/BindMapAsMetadataTest.java
new file mode 100644
index 0000000..9c6d056
--- /dev/null
+++ b/labs/vcloud-director/src/test/java/org/jclouds/vcloud/director/v1_5/binders/BindMapAsMetadataTest.java
@@ -0,0 +1,57 @@
+/*
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ *(Link.builder().regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless(Link.builder().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.vcloud.director.v1_5.binders;
+
+import static org.testng.Assert.assertEquals;
+
+import javax.ws.rs.core.MediaType;
+
+import org.jclouds.http.HttpRequest;
+import org.jclouds.xml.XMLParser;
+import org.jclouds.xml.internal.JAXBParser;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.ImmutableMap;
+
+/**
+ * Tests behavior of {@code BindMapAsMetadata}.
+ * 
+ */
+@Test(groups = "unit", testName = "BindMapAsMetadataTest")
+public class BindMapAsMetadataTest {
+   XMLParser xml = new JAXBParser("true");
+
+   @Test
+   public void testBindMap() {
+      BindMapAsMetadata binder = new BindMapAsMetadata(xml);
+
+      HttpRequest request = HttpRequest.builder().method("GET").endpoint("http://momma").build();
+      request = binder.bindToRequest(request, ImmutableMap.of("foo", "bar"));
+      assertEquals(request.getPayload().getRawContent(), 
+                  XMLParser.DEFAULT_XML_HEADER + "\n"+
+                  "<Metadata xmlns=\"http://www.vmware.com/vcloud/v1.5\">" + "\n"+
+                  "    <MetadataEntry>" + "\n" +
+                  "        <Key>foo</Key>" + "\n" +
+                  "        <Value>bar</Value>" + "\n" +
+                  "    </MetadataEntry>" + "\n" +
+                  "</Metadata>" + "\n");
+      assertEquals(request.getPayload().getContentMetadata().getContentType(), MediaType.APPLICATION_XML);
+   }
+
+}
diff --git a/labs/vcloud-director/src/test/java/org/jclouds/vcloud/director/v1_5/binders/BindStringAsMetadataValueTest.java b/labs/vcloud-director/src/test/java/org/jclouds/vcloud/director/v1_5/binders/BindStringAsMetadataValueTest.java
new file mode 100644
index 0000000..e7a2485
--- /dev/null
+++ b/labs/vcloud-director/src/test/java/org/jclouds/vcloud/director/v1_5/binders/BindStringAsMetadataValueTest.java
@@ -0,0 +1,52 @@
+/*
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ *(Link.builder().regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless(Link.builder().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.vcloud.director.v1_5.binders;
+
+import static org.testng.Assert.assertEquals;
+
+import javax.ws.rs.core.MediaType;
+
+import org.jclouds.http.HttpRequest;
+import org.jclouds.xml.XMLParser;
+import org.jclouds.xml.internal.JAXBParser;
+import org.testng.annotations.Test;
+
+/**
+ * Tests behavior of {@code BindStringAsMetadataValue}.
+ * 
+ */
+@Test(groups = "unit", testName = "BindStringAsMetadataValueTest")
+public class BindStringAsMetadataValueTest {
+   XMLParser xml = new JAXBParser("true");
+
+   @Test
+   public void testBindMap() {
+      BindStringAsMetadataValue binder = new BindStringAsMetadataValue(xml);
+
+      HttpRequest request = HttpRequest.builder().method("GET").endpoint("http://momma").build();
+      request = binder.bindToRequest(request, "foo");
+      assertEquals(request.getPayload().getRawContent(), 
+                  XMLParser.DEFAULT_XML_HEADER + "\n"+
+                  "<MetadataValue xmlns=\"http://www.vmware.com/vcloud/v1.5\">" + "\n"+
+                  "    <Value>foo</Value>" + "\n" +
+                  "</MetadataValue>" + "\n");
+      assertEquals(request.getPayload().getContentMetadata().getContentType(), MediaType.APPLICATION_XML);
+   }
+
+}
diff --git a/labs/vcloud-director/src/test/java/org/jclouds/vcloud/director/v1_5/domain/Checks.java b/labs/vcloud-director/src/test/java/org/jclouds/vcloud/director/v1_5/domain/Checks.java
index fa1e6d1..017af88 100644
--- a/labs/vcloud-director/src/test/java/org/jclouds/vcloud/director/v1_5/domain/Checks.java
+++ b/labs/vcloud-director/src/test/java/org/jclouds/vcloud/director/v1_5/domain/Checks.java
@@ -141,7 +141,7 @@
       }
       
       // Check parent type
-      checkResourceType(entity);
+      checkResource(entity);
    }
 
    /**
@@ -173,20 +173,20 @@
    /**
     * Assumes the validTypes to be vcloud-specific types.
     * 
-    * @see #checkResourceType(ResourceType, Collection)
+    * @see #checkResource(Resource, Collection)
     */
-   public static void checkResourceType(Resource resource) {
-      checkResourceType(resource, VCloudDirectorMediaType.ALL);
+   public static void checkResource(Resource resource) {
+      checkResource(resource, VCloudDirectorMediaType.ALL);
    }
 
    /**
-    * @see #checkResourceType(ResourceType, Collection)
+    * @see #checkResource(Resource, Collection)
     */
-   public static void checkResourceType(Resource resource, String type) {
-      checkResourceType(resource, ImmutableSet.of(type));
+   public static void checkResource(Resource resource, String type) {
+      checkResource(resource, ImmutableSet.of(type));
    }
 
-   public static void checkResourceType(Resource resource, Collection<String> validTypes) {
+   public static void checkResource(Resource resource, Collection<String> validTypes) {
       // Check optional fields
       URI href = resource.getHref();
       if (href != null) checkHref(href);
@@ -294,7 +294,7 @@
       }
 
       // Check parent type
-      checkResourceType(metadata);
+      checkResource(metadata);
    }
 
    public static void checkMetadataEntry(MetadataEntry metadataEntry) {
@@ -303,15 +303,7 @@
       assertNotNull(metadataEntry.getValue(), String.format(NOT_NULL_OBJ_FIELD_FMT, "Value", "MetadataEntry"));
 
       // Check parent type
-      checkResourceType(metadataEntry);
-   }
-
-   public static void checkMetadataValue(MetadataValue metadataValue) {
-      // Check required elements and attributes
-      assertNotNull(metadataValue.getValue(), String.format(NOT_NULL_OBJ_FIELD_FMT, "Value", "MetadataValue"));
-      
-      // Check parent type
-      checkResourceType(metadataValue);
+      checkResource(metadataEntry);
    }
 
    public static void checkProgress(Integer progress) {
@@ -339,7 +331,7 @@
    public static void checkAdminOrg(AdminOrg org) {
       // required
       assertNotNull(org.getSettings(), String.format(NOT_NULL_OBJ_FIELD_FMT, "settings", "AdminOrg"));
-      checkResourceType(org, VCloudDirectorMediaType.ADMIN_ORG);
+      checkResource(org, VCloudDirectorMediaType.ADMIN_ORG);
       
       // optional
       for (Reference user : org.getUsers()) {
@@ -387,7 +379,7 @@
       }
       
      // Check parent type
-      checkResourceType(owner);
+      checkResource(owner);
    }
 
    public static void checkCatalogItem(CatalogItem catalogItem) {
@@ -573,29 +565,13 @@
                String.format(OBJ_FIELD_ATTRB_REQ, api, "MetadataEntry", entry.getValue(), "value"));
           
          // Check parent type
-         checkResourceType(entry);
+         checkResource(entry);
       }
       
       // Check parent type
-      checkResourceType(metadata);
+      checkResource(metadata);
    }
 
-   public static void checkMetadataValueFor(String api, MetadataValue metadataValue) {
-      checkMetadataValueFor(api, metadataValue, "value");
-   }
-   
-   public static void checkMetadataValueFor(String api, MetadataValue metadataValue, String expectedValue) {
-      // Check required fields
-      String value = metadataValue.getValue();
-      assertNotNull(value, 
-            String.format(OBJ_FIELD_ATTRB_REQ, api, "MetadataEntry", 
-                  metadataValue.toString(), "value"));
-      assertEquals(value, expectedValue, 
-            String.format(OBJ_FIELD_EQ, api, "metadataEntry.value", expectedValue, value));
-      
-      // Check parent type
-      checkResourceType(metadataValue);
-   }
 
    public static void checkMetadataKeyAbsentFor(String api, Metadata metadata, String key) {
       Map<String,String> metadataMap = metadataToMap(metadata);
@@ -628,7 +604,7 @@
       }
       
       // Check parent type
-      checkResourceType(question);
+      checkResource(question);
    }
 
    public static void checkVmQuestionAnswerChoice(VmQuestionAnswerChoice choice) {
@@ -848,7 +824,7 @@
       }
       
       // parent type
-      checkResourceType(settings);
+      checkResource(settings);
    }
    
    public static void checkEmailSettings(OrgEmailSettings settings) {
@@ -864,7 +840,7 @@
       // NOTE alertEmailsTo cannot be checked
       
       // parent type
-      checkResourceType(settings);
+      checkResource(settings);
    }
    
    public static void checkEmailAddress(String email) {
@@ -889,7 +865,7 @@
       }
       
       // parent type
-      checkResourceType(settings);
+      checkResource(settings);
    }
    
    public static void checkLdapSettings(OrgLdapSettings settings) {
@@ -905,7 +881,7 @@
       }
       
       // parent type
-      checkResourceType(settings);
+      checkResource(settings);
    }
    
    public static void checkCustomOrgLdapSettings(CustomOrgLdapSettings settings) {
@@ -980,7 +956,7 @@
             String.format(OBJ_FIELD_GTE_0, "OrgPasswordPolicySettings", "accountLockoutIntervalMinutes", settings.getAccountLockoutIntervalMinutes()));
       
       // parent type
-      checkResourceType(settings);
+      checkResource(settings);
    }
    
    public static void checkVAppLeaseSettings(OrgLeaseSettings settings) {
@@ -996,7 +972,7 @@
       }
       
       // parent type
-      checkResourceType(settings);
+      checkResource(settings);
    }
 
    public static void checkVAppTemplateLeaseSettings(OrgVAppTemplateLeaseSettings settings) {
@@ -1008,7 +984,7 @@
       }
       
       // parent type
-      checkResourceType(settings);
+      checkResource(settings);
    }
    
    public static void checkUser(User user) {
@@ -1087,7 +1063,7 @@
       }
       
       // Check parent type
-      checkResourceType(sections);
+      checkResource(sections);
    }
 
    public static void checkGuestCustomizationSection(GuestCustomizationSection section) {
@@ -1220,7 +1196,7 @@
       assertNotNull(val.getNetworkName(), String.format(NOT_NULL_OBJ_FIELD_FMT, "NetworkName", "VAppNetworkConfiguration"));
       checkNetworkConfiguration(val.getConfiguration());
       
-      checkResourceType(val);
+      checkResource(val);
    }
 
    public static void checkNetworkConnectionSection(NetworkConnectionSection val) {
@@ -1517,6 +1493,6 @@
       }
          
       // parent type
-      checkResourceType(container);
+      checkResource(container);
    }
 }
diff --git a/labs/vcloud-director/src/test/java/org/jclouds/vcloud/director/v1_5/features/CatalogApiExpectTest.java b/labs/vcloud-director/src/test/java/org/jclouds/vcloud/director/v1_5/features/CatalogApiExpectTest.java
index 365a90c..54fc861 100644
--- a/labs/vcloud-director/src/test/java/org/jclouds/vcloud/director/v1_5/features/CatalogApiExpectTest.java
+++ b/labs/vcloud-director/src/test/java/org/jclouds/vcloud/director/v1_5/features/CatalogApiExpectTest.java
@@ -37,12 +37,12 @@
 import org.jclouds.vcloud.director.v1_5.domain.Link;
 import org.jclouds.vcloud.director.v1_5.domain.Metadata;
 import org.jclouds.vcloud.director.v1_5.domain.MetadataEntry;
-import org.jclouds.vcloud.director.v1_5.domain.MetadataValue;
 import org.jclouds.vcloud.director.v1_5.domain.Reference;
 import org.jclouds.vcloud.director.v1_5.domain.Task;
 import org.jclouds.vcloud.director.v1_5.user.VCloudDirectorApi;
 import org.testng.annotations.Test;
 
+import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.ImmutableSet;
 import com.google.common.net.HttpHeaders;
 
@@ -182,7 +182,7 @@
    @Test
    public void testGetCatalogMetadataEntryHref() {
       VCloudDirectorApi api = requestsSendResponses(loginRequest, sessionResponse, getMetadataValue, getMetadataValueResponse);
-      assertEquals(api.getCatalogApi().getMetadataApi(catalogHref).getValue("KEY"), metadataValue());
+      assertEquals(api.getCatalogApi().getMetadataApi(catalogHref).get("KEY"), "VALUE");
    }
 
    static String item = "a36fdac9-b8c2-43e2-9a4c-2ffaf3ee13df";
@@ -328,9 +328,7 @@
    @Test
    public void testMergeCatalogItemMetadataHref() {
       VCloudDirectorApi api = requestsSendResponses(loginRequest, sessionResponse, mergeItemMetadata, mergeItemMetadataResponse);
-      // TODO: horrendous way of representing Map<String,String>
-      Metadata metadata = Metadata.builder().entry(MetadataEntry.builder().entry("KEY", "VALUE").build()).build();
-      assertEquals(api.getCatalogApi().getItemMetadataApi(itemHref).merge(metadata), mergeMetadataTask());
+      assertEquals(api.getCatalogApi().getItemMetadataApi(itemHref).putAll(ImmutableMap.of("KEY", "VALUE")), mergeMetadataTask());
    }
    
    HttpRequest getItemMetadataValue = HttpRequest.builder()
@@ -348,7 +346,7 @@
    @Test
    public void testGetCatalogItemMetadataEntryHref() {
       VCloudDirectorApi api = requestsSendResponses(loginRequest, sessionResponse, getItemMetadataValue, getItemMetadataValueResponse);
-      assertEquals(api.getCatalogApi().getMetadataApi(itemHref).getValue("KEY"), itemMetadataValue());
+      assertEquals(api.getCatalogApi().getMetadataApi(itemHref).get("KEY"), "VALUE");
    }
    
    HttpRequest putItemMetadata = HttpRequest.builder()
@@ -368,7 +366,7 @@
    @Test
    public void testSetCatalogItemMetadataEntryHref() {
       VCloudDirectorApi api = requestsSendResponses(loginRequest, sessionResponse, putItemMetadata, putItemMetadataResponse);
-      assertEquals(api.getCatalogApi().getItemMetadataApi(itemHref).putEntry("KEY", MetadataValue.builder().value("KITTENS").build()), setMetadataValueTask());
+      assertEquals(api.getCatalogApi().getItemMetadataApi(itemHref).put("KEY", "KITTENS"), setMetadataValueTask());
    }
    
    HttpRequest removeItemMetadataEntry = HttpRequest.builder()
@@ -386,7 +384,7 @@
    @Test
    public void testRemoveCatalogItemMetadataEntryHref() {
       VCloudDirectorApi api = requestsSendResponses(loginRequest, sessionResponse, removeItemMetadataEntry, removeItemMetadataEntryResponse);
-      assertEquals(api.getCatalogApi().getItemMetadataApi(itemHref).removeEntry("KEY"), removeEntryTask());
+      assertEquals(api.getCatalogApi().getItemMetadataApi(itemHref).remove("KEY"), removeTask());
    }
    
    public static final Catalog catalog() {
@@ -486,30 +484,6 @@
                   .entry("KEY", "VALUE")
                   .build();
    }
-
-   public static MetadataValue metadataValue() {
-      return  MetadataValue.builder()
-                  .href(URI.create(endpoint + "/catalog/" + catalog + "/metadata/KEY"))
-                  .link(Link.builder()
-                        .rel("up")
-                        .type("application/vnd.vmware.vcloud.metadata+xml")
-                        .href(URI.create(endpoint + "/catalog/" + catalog + "/metadata"))
-                        .build())
-                  .value("VALUE")
-                  .build();
-   }
-
-   public static MetadataValue itemMetadataValue() {
-      return  MetadataValue.builder()
-                  .href(URI.create(endpoint + "/catalogItem/" + item + "/metadata/KEY"))
-                  .link(Link.builder()
-                        .rel("up")
-                        .type("application/vnd.vmware.vcloud.metadata+xml")
-                        .href(URI.create(endpoint + "/catalogItem/" + item + "/metadata"))
-                        .build())
-                  .value("VALUE")
-                  .build();
-   }
    
    public static CatalogItem catalogItem() {
       return CatalogItem.builder()
@@ -607,7 +581,7 @@
             .build();
    }
 
-   public static Task removeEntryTask() {
+   public static Task removeTask() {
       return Task.builder()
             .name("task")
             .id("urn:vcloud:task:c6dca927-eab4-41fa-ad6a-3ac58602541c")
diff --git a/labs/vcloud-director/src/test/java/org/jclouds/vcloud/director/v1_5/features/CatalogApiLiveTest.java b/labs/vcloud-director/src/test/java/org/jclouds/vcloud/director/v1_5/features/CatalogApiLiveTest.java
index 50075aa..5c409a0 100644
--- a/labs/vcloud-director/src/test/java/org/jclouds/vcloud/director/v1_5/features/CatalogApiLiveTest.java
+++ b/labs/vcloud-director/src/test/java/org/jclouds/vcloud/director/v1_5/features/CatalogApiLiveTest.java
@@ -24,7 +24,6 @@
 import static org.jclouds.vcloud.director.v1_5.VCloudDirectorLiveTestConstants.TASK_COMPLETE_TIMELY;
 import static org.jclouds.vcloud.director.v1_5.domain.Checks.checkCatalogItem;
 import static org.jclouds.vcloud.director.v1_5.domain.Checks.checkMetadata;
-import static org.jclouds.vcloud.director.v1_5.domain.Checks.checkMetadataValue;
 import static org.jclouds.vcloud.director.v1_5.domain.Checks.checkTask;
 import static org.jclouds.vcloud.director.v1_5.predicates.LinkPredicates.relEquals;
 import static org.jclouds.vcloud.director.v1_5.predicates.LinkPredicates.typeEquals;
@@ -41,19 +40,15 @@
 import org.jclouds.vcloud.director.v1_5.domain.Link;
 import org.jclouds.vcloud.director.v1_5.domain.Media;
 import org.jclouds.vcloud.director.v1_5.domain.Metadata;
-import org.jclouds.vcloud.director.v1_5.domain.MetadataEntry;
-import org.jclouds.vcloud.director.v1_5.domain.MetadataValue;
 import org.jclouds.vcloud.director.v1_5.domain.Reference;
 import org.jclouds.vcloud.director.v1_5.domain.Task;
 import org.jclouds.vcloud.director.v1_5.domain.Vdc;
-import org.jclouds.vcloud.director.v1_5.domain.org.Org;
 import org.jclouds.vcloud.director.v1_5.features.admin.AdminCatalogApi;
 import org.jclouds.vcloud.director.v1_5.internal.BaseVCloudDirectorApiLiveTest;
 import org.testng.annotations.AfterClass;
 import org.testng.annotations.Test;
 
-import com.google.common.base.Predicate;
-import com.google.common.collect.Iterables;
+import com.google.common.collect.ImmutableMap;
 
 /**
  * Tests live behavior of {@link CatalogApi}.
@@ -74,44 +69,29 @@
    private AdminCatalog adminCatalog;
    private Media media;
    private CatalogItem catalogItem;
-
+   private boolean createdByTest = false;
+   private AdminCatalogApi adminCatalogApi;
+   
    @Override
    protected void setupRequiredApis() {
-      // TODO why do I need a guard clause here?
-      if (adminCatalog != null)
-         return;
       catalogApi = context.getApi().getCatalogApi();
-      Org org = context.getApi().getOrgApi().get(Iterables.get(context.getApi().getOrgApi().list(), 0).getHref());
-
-      if (adminContext != null) {
+      adminCatalogApi = adminContext.getApi().getCatalogApi();
+     
+      if(catalogUrn == null) {
          AdminCatalog newCatalog = AdminCatalog.builder().name(name("Test Catalog "))
                   .description("created by CatalogApiLiveTest").build();
 
-         AdminCatalogApi adminCatalogApi = adminContext.getApi().getCatalogApi();
          adminCatalog = adminCatalogApi.addCatalogToOrg(newCatalog, org.getId());
          catalogUrn = catalogApi.get(
                   find(adminCatalog.getLinks(),
                            and(relEquals("alternate"), typeEquals(VCloudDirectorMediaType.CATALOG))).getHref()).getId();
 
-         Metadata newMetadata = Metadata.builder().entry(MetadataEntry.builder().entry("KEY", "MARMALADE").build())
-                  .build();
-
-         Task mergeCatalogMetadata = adminCatalogApi.getMetadataApi(adminCatalog.getId()).merge(newMetadata);
-         checkTask(mergeCatalogMetadata);
-         assertTrue(retryTaskSuccess.apply(mergeCatalogMetadata),
-                  String.format(TASK_COMPLETE_TIMELY, "setupRequiredApis"));
+         createdByTest = true;
       }
    }
 
    @AfterClass(alwaysRun = true)
    public void tearDown() {
-      if (catalogItem != null) {
-         try {
-            catalogApi.removeItem(catalogItem.getId());
-         } catch (Exception e) {
-            logger.warn(e, "Error when deleting catalog item '%s'", catalogItem.getName());
-         }
-      }
       if (media != null) {
          try {
             Task remove = context.getApi().getMediaApi().remove(media.getId());
@@ -120,14 +100,22 @@
             logger.warn(e, "Error when deleting media '%s'", media.getName());
          }
       }
-      if (adminContext != null && adminCatalog != null) {
-         try {
-            adminContext.getApi().getCatalogApi().remove(adminCatalog.getId());
-         } catch (Exception e) {
-            logger.warn(e, "Error when deleting catalog '%s'", adminCatalog.getName());
+      if(createdByTest) {
+         if (catalogItem != null) {
+            try {
+               catalogApi.removeItem(catalogItem.getId());
+            } catch (Exception e) {
+               logger.warn(e, "Error when deleting catalog item '%s'", catalogItem.getName());
+            }
+         }
+         if (adminContext != null && adminCatalog != null) {
+            try {
+               adminContext.getApi().getCatalogApi().remove(adminCatalog.getId());
+            } catch (Exception e) {
+               logger.warn(e, "Error when deleting catalog '%s'", adminCatalog.getName());
+            }
          }
       }
-      // TODO wait for tasks
    }
 
    @Test(description = "GET /catalog/{id}")
@@ -151,7 +139,7 @@
       Vdc vdc = lazyGetVdc();
       Link addMedia = find(vdc.getLinks(), and(relEquals("add"), typeEquals(VCloudDirectorMediaType.MEDIA)));
 
-      Media sourceMedia = Media.builder().type(VCloudDirectorMediaType.MEDIA).name("Test media 1").size(iso.length)
+      Media sourceMedia = Media.builder().type(VCloudDirectorMediaType.MEDIA).name(name("TestMedia-")).size(iso.length)
                .imageType(Media.ImageType.ISO).description("Test media generated by testAddMedia()").build();
       media = context.getApi().getMediaApi().add(addMedia.getHref(), sourceMedia);
 
@@ -177,6 +165,7 @@
    // Note this runs after all the metadata tests
    @Test(description = "DELETE /catalogItem/{id}", dependsOnMethods = "testRemoveCatalogItemMetadataValue")
    public void testRemoveCatalogItem() {
+      removeMediaAttachedToCatalogItem(catalogItem);
       catalogApi.removeItem(catalogItem.getId());
       catalogItem = catalogApi.getItem(catalogItem.getId());
       assertNull(catalogItem);
@@ -190,19 +179,16 @@
 
    @Test(description = "GET /catalog/{id}/metadata/{key}")
    public void testGetCatalogMetadataValue() {
+
+      Task mergeCatalogMetadata = adminCatalogApi.getMetadataApi(catalogUrn)
+            .putAll(ImmutableMap.of("KEY", "MARMALADE"));
+      assertTaskSucceedsLong(mergeCatalogMetadata);
+
       Metadata catalogMetadata = catalogApi.getMetadataApi(catalogUrn).get();
-      MetadataEntry existingMetadataEntry = Iterables.find(catalogMetadata.getMetadataEntries(),
-               new Predicate<MetadataEntry>() {
-                  @Override
-                  public boolean apply(MetadataEntry input) {
-                     return input.getKey().equals("KEY");
-                  }
-               });
-      MetadataValue metadataValue = catalogApi.getMetadataApi(catalogApi.get(existingMetadataEntry.getHref()).getId())
-               .getValue("KEY");
-      assertEquals(metadataValue.getValue(), existingMetadataEntry.getValue(), String.format(CORRECT_VALUE_OBJECT_FMT,
-               "Value", "MetadataValue", existingMetadataEntry.getValue(), metadataValue.getValue()));
-      checkMetadataValue(metadataValue);
+
+      String metadataValue = catalogApi.getMetadataApi(catalogUrn).get("KEY");
+      assertEquals(metadataValue, catalogMetadata.get("KEY"), String.format(CORRECT_VALUE_OBJECT_FMT, "Value",
+            "MetadataValue", catalogMetadata.get("KEY"), metadataValue));
    }
 
    @Test(description = "GET /catalogItem/{id}/metadata", dependsOnMethods = "testAddCatalogItem")
@@ -213,61 +199,66 @@
 
    @Test(description = "POST /catalogItem/{id}/metadata", dependsOnMethods = "testAddCatalogItem")
    public void testMergeCatalogItemMetadata() {
-      Metadata newMetadata = Metadata.builder().entry(MetadataEntry.builder().entry("KEY", "MARMALADE").build())
-               .entry(MetadataEntry.builder().entry("VEGIMITE", "VALUE").build()).build();
-
       Metadata before = catalogApi.getItemMetadataApi(catalogItem.getId()).get();
 
-      Task mergeCatalogItemMetadata = catalogApi.getItemMetadataApi(catalogItem.getId()).merge(newMetadata);
+      Task mergeCatalogItemMetadata = catalogApi.getItemMetadataApi(catalogItem.getId()).putAll(
+            ImmutableMap.of("KEY", "MARMALADE", "VEGIMITE", "VALUE"));
       checkTask(mergeCatalogItemMetadata);
       assertTrue(retryTaskSuccess.apply(mergeCatalogItemMetadata),
-               String.format(TASK_COMPLETE_TIMELY, "mergeCatalogItemMetadata"));
+            String.format(TASK_COMPLETE_TIMELY, "mergeCatalogItemMetadata"));
       Metadata mergedCatalogItemMetadata = catalogApi.getItemMetadataApi(catalogItem.getId()).get();
 
       assertTrue(mergedCatalogItemMetadata.getMetadataEntries().size() > before.getMetadataEntries().size(),
-               "Should have added at least one other MetadataEntry to the CatalogItem");
+            "Should have added at least one other MetadataEntry to the CatalogItem");
 
-      MetadataValue keyMetadataValue = catalogApi.getItemMetadataApi(catalogItem.getId()).getValue("KEY");
-      assertEquals(keyMetadataValue.getValue(), "MARMALADE",
-               "The Value of the MetadataValue for KEY should have changed");
-      checkMetadataValue(keyMetadataValue);
+      String keyMetadataValue = catalogApi.getItemMetadataApi(catalogItem.getId()).get("KEY");
+      assertEquals(keyMetadataValue, "MARMALADE", "The Value of the MetadataValue for KEY should have changed");
 
-      MetadataValue newKeyMetadataValue = catalogApi.getItemMetadataApi(catalogItem.getId()).getValue("VEGIMITE");
+      String newKeyMetadataValue = catalogApi.getItemMetadataApi(catalogItem.getId()).get("VEGIMITE");
 
-      assertEquals(newKeyMetadataValue.getValue(), "VALUE",
-               "The Value of the MetadataValue for NEW_KEY should have been set");
-      checkMetadataValue(newKeyMetadataValue);
+      assertEquals(newKeyMetadataValue, "VALUE", "The Value of the MetadataValue for NEW_KEY should have been set");
    }
 
    @Test(description = "GET /catalogItem/{id}/metadata/{key}", dependsOnMethods = "testSetCatalogItemMetadataValue")
    public void testGetCatalogItemMetadataValue() {
-      MetadataValue metadataValue = catalogApi.getItemMetadataApi(catalogItem.getId()).getValue("KEY");
-      checkMetadataValue(metadataValue);
+      String metadataValue = catalogApi.getItemMetadataApi(catalogItem.getId()).get("KEY");
+      assertNotNull(metadataValue);
    }
 
    @Test(description = "PUT /catalogItem/{id}/metadata/{key}", dependsOnMethods = "testMergeCatalogItemMetadata")
    public void testSetCatalogItemMetadataValue() {
-      MetadataValue newMetadataValue = MetadataValue.builder().value("NEW").build();
 
-      Task setCatalogItemMetadataValue = catalogApi.getItemMetadataApi(catalogItem.getId()).putEntry("KEY",
-               newMetadataValue);
+      Task setCatalogItemMetadataValue = catalogApi.getItemMetadataApi(catalogItem.getId()).put("KEY", "NEW");
       checkTask(setCatalogItemMetadataValue);
       assertTrue(retryTaskSuccess.apply(setCatalogItemMetadataValue),
-               String.format(TASK_COMPLETE_TIMELY, "setCatalogItemMetadataValue"));
+            String.format(TASK_COMPLETE_TIMELY, "setCatalogItemMetadataValue"));
 
-      MetadataValue editedMetadataValue = catalogApi.getItemMetadataApi(catalogItem.getId()).getValue("KEY");
-      assertEquals(editedMetadataValue.getValue(), newMetadataValue.getValue(), String.format(CORRECT_VALUE_OBJECT_FMT,
-               "Value", "MetadataValue", newMetadataValue.getValue(), editedMetadataValue.getValue()));
-      checkMetadataValue(editedMetadataValue);
+      String editedMetadataValue = catalogApi.getItemMetadataApi(catalogItem.getId()).get("KEY");
+      assertEquals(editedMetadataValue, "NEW",
+            String.format(CORRECT_VALUE_OBJECT_FMT, "Value", "MetadataValue", "NEW", editedMetadataValue));
    }
 
    @Test(description = "DELETE /catalogItem/{id}/metadata/{key}", dependsOnMethods = "testGetCatalogItemMetadataValue")
    public void testRemoveCatalogItemMetadataValue() {
-      Task removeCatalogItemMetadataValue = catalogApi.getItemMetadataApi(catalogItem.getId()).removeEntry("KEY");
+      Task removeCatalogItemMetadataValue = catalogApi.getItemMetadataApi(catalogItem.getId()).remove("KEY");
       checkTask(removeCatalogItemMetadataValue);
       assertTrue(retryTaskSuccess.apply(removeCatalogItemMetadataValue),
-               String.format(TASK_COMPLETE_TIMELY, "removeCatalogItemMetadataValue"));
-      MetadataValue removed = catalogApi.getItemMetadataApi(catalogItem.getId()).getValue("KEY");
+            String.format(TASK_COMPLETE_TIMELY, "removeCatalogItemMetadataValue"));
+      String removed = catalogApi.getItemMetadataApi(catalogItem.getId()).get("KEY");
       assertNull(removed);
    }
+   
+   private void removeMediaAttachedToCatalogItem(CatalogItem catalogItem) {
+      if (media != null) {
+         if (catalogItem.getEntity().getHref().equals(media.getHref())) {
+            try {
+               Task remove = context.getApi().getMediaApi().remove(media.getId());
+               taskDoneEventually(remove);
+               media = null;
+            } catch (Exception e) {
+               logger.warn(e, "Error when deleting media '%s'", media.getName());
+            }
+         }
+      }
+   }   
 }
diff --git a/labs/vcloud-director/src/test/java/org/jclouds/vcloud/director/v1_5/features/KeyPairsApiLiveTest.java b/labs/vcloud-director/src/test/java/org/jclouds/vcloud/director/v1_5/features/KeyPairsApiLiveTest.java
new file mode 100644
index 0000000..d654568
--- /dev/null
+++ b/labs/vcloud-director/src/test/java/org/jclouds/vcloud/director/v1_5/features/KeyPairsApiLiveTest.java
@@ -0,0 +1,217 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ *(Link.builder().regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless(Link.builder().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.vcloud.director.v1_5.features;
+
+import static com.google.common.base.Predicates.and;
+import static com.google.common.collect.Iterables.find;
+import static com.google.common.collect.Iterables.getFirst;
+import static org.jclouds.vcloud.director.v1_5.VCloudDirectorLiveTestConstants.OBJ_DEL;
+import static org.jclouds.vcloud.director.v1_5.VCloudDirectorLiveTestConstants.OBJ_FIELD_EQ;
+import static org.jclouds.vcloud.director.v1_5.VCloudDirectorLiveTestConstants.OBJ_FIELD_LIST_SIZE_EQ;
+import static org.jclouds.vcloud.director.v1_5.VCloudDirectorLiveTestConstants.OBJ_FIELD_LIST_SIZE_GE;
+import static org.jclouds.vcloud.director.v1_5.VCloudDirectorLiveTestConstants.OBJ_FIELD_REQ;
+import static org.jclouds.vcloud.director.v1_5.VCloudDirectorLiveTestConstants.TASK_COMPLETE_TIMELY;
+import static org.jclouds.vcloud.director.v1_5.predicates.LinkPredicates.relEquals;
+import static org.jclouds.vcloud.director.v1_5.predicates.LinkPredicates.typeEquals;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertNull;
+import static org.testng.Assert.assertTrue;
+
+import java.net.URISyntaxException;
+import java.util.Map;
+import java.util.Set;
+
+import org.jclouds.crypto.SshKeys;
+import org.jclouds.io.Payloads;
+import org.jclouds.json.Json;
+import org.jclouds.vcloud.director.v1_5.VCloudDirectorMediaType;
+import org.jclouds.vcloud.director.v1_5.domain.Checks;
+import org.jclouds.vcloud.director.v1_5.domain.File;
+import org.jclouds.vcloud.director.v1_5.domain.Link;
+import org.jclouds.vcloud.director.v1_5.domain.Media;
+import org.jclouds.vcloud.director.v1_5.domain.Task;
+import org.jclouds.vcloud.director.v1_5.domain.Vdc;
+import org.jclouds.vcloud.director.v1_5.internal.BaseVCloudDirectorApiLiveTest;
+import org.jclouds.vcloud.director.v1_5.predicates.LinkPredicates;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+import org.testng.collections.Maps;
+
+import com.google.common.base.Optional;
+import com.google.common.base.Predicate;
+import com.google.common.base.Predicates;
+import com.google.common.collect.Iterables;
+import com.google.inject.Inject;
+
+/**
+ * Tests behavior of {@code Key Pairs}
+ * 
+ * @author andrea turli
+ */
+@Test(groups = { "live", "user" }, singleThreaded = true, testName = "KeyPairsApiLiveTest")
+public class KeyPairsApiLiveTest extends BaseVCloudDirectorApiLiveTest {
+
+	@Inject
+	protected Json json;
+	public static final String MEDIA = "media";
+
+	protected VdcApi vdcApi;
+	protected MediaApi mediaApi;
+
+	private Map<String, String> sshKey;
+	private String keyPairContainer = "keypairs";
+
+	@Override
+	@BeforeClass(alwaysRun = true)
+	public void setupRequiredApis() {
+		vdcApi = context.getApi().getVdcApi();
+		mediaApi = context.getApi().getMediaApi();
+	}
+
+	@Test(description = "Create Key Pair")
+	public void testCreateKeyPair() throws URISyntaxException {
+		sshKey = SshKeys.generate();
+		String keyPairName = "NewKeyPair";
+		Vdc currentVDC = lazyGetVdc();
+		Media keyPairsContainer = findOrCreateKeyPairContainerInVDCNamed(currentVDC,
+				keyPairContainer, keyPairName);
+		String keypairValue = mediaApi.getMetadataApi(
+				keyPairsContainer.getId()).get(keyPairName);
+		assertEquals(keypairValue, generateKeyPair(keyPairName));
+	}
+
+	@Test(description = "DeleteKeyPair", dependsOnMethods = { "testCreateKeyPair" })
+	public void testDeleteKeyPair() {
+		String keyPairName = "NewKeyPair";
+		Vdc currentVDC = lazyGetVdc();
+		Media keyPairsContainer = findOrCreateKeyPairContainerInVDCNamed(currentVDC,
+				keyPairContainer, keyPairName);
+		Task removeMedia = mediaApi.remove(keyPairsContainer.getId());
+		Checks.checkTask(removeMedia);
+		assertTrue(retryTaskSuccess.apply(removeMedia),
+				String.format(TASK_COMPLETE_TIMELY, "removeMedia"));
+
+		keyPairsContainer = mediaApi.get(keyPairsContainer.getId());
+		assertNull(keyPairsContainer, String.format(OBJ_DEL, MEDIA,
+				keyPairsContainer != null ? keyPairsContainer.toString() : ""));
+	}
+
+	private Media findOrCreateKeyPairContainerInVDCNamed(Vdc currentVDC,
+			String keyPairsContainerName, final String keyPairName) {
+		Media keyPairsContainer = null;
+
+		Optional<Media> optionalKeyPairsContainer = Iterables.tryFind(
+				findAllEmptyMediaInOrg(), new Predicate<Media>() {
+
+					@Override
+					public boolean apply(Media input) {
+						return mediaApi.getMetadataApi(input.getId()).get(
+								keyPairName) != null;
+					}
+				});
+
+		if (optionalKeyPairsContainer.isPresent())
+			keyPairsContainer = optionalKeyPairsContainer.get();
+
+		if (keyPairsContainer == null) {
+			keyPairsContainer = uploadKeyPairInVCD(currentVDC,
+					keyPairsContainerName, keyPairName);
+		}
+		return keyPairsContainer;
+	}
+
+	private Media uploadKeyPairInVCD(Vdc currentVDC,
+			String keyPairsContainerName, String keyPairName) {
+		Media keyPairsContainer = addEmptyMediaInVDC(currentVDC,
+				keyPairsContainerName);
+		assertNotNull(keyPairsContainer.getFiles(),
+				String.format(OBJ_FIELD_REQ, MEDIA, "files"));
+		assertTrue(keyPairsContainer.getFiles().size() == 1, String.format(
+				OBJ_FIELD_LIST_SIZE_EQ, MEDIA, "files", 1, keyPairsContainer
+						.getFiles().size()));
+
+		Link uploadLink = getUploadLinkForMedia(keyPairsContainer);
+		// generate an empty iso
+		byte[] iso = new byte[] {};
+		context.getApi()
+				.getUploadApi()
+				.upload(uploadLink.getHref(), Payloads.newByteArrayPayload(iso));
+
+		Checks.checkMediaFor(VCloudDirectorMediaType.MEDIA, keyPairsContainer);
+		setKeyPairOnkeyPairsContainer(keyPairsContainer, keyPairName, generateKeyPair(keyPairName));
+
+		return keyPairsContainer;
+	}
+
+	private Link getUploadLinkForMedia(Media emptyMedia) {
+		File uploadFile = getFirst(emptyMedia.getFiles(), null);
+		assertNotNull(uploadFile,
+				String.format(OBJ_FIELD_REQ, MEDIA, "files.first"));
+		assertEquals(uploadFile.getSize(), Long.valueOf(0));
+		assertEquals(uploadFile.getSize().longValue(), emptyMedia.getSize(),
+				String.format(OBJ_FIELD_EQ, MEDIA, "uploadFile.size()",
+						emptyMedia.getSize(), uploadFile.getSize()));
+
+		Set<Link> links = uploadFile.getLinks();
+		assertNotNull(links,
+				String.format(OBJ_FIELD_REQ, MEDIA, "uploadFile.links"));
+		assertTrue(links.size() >= 1, String.format(OBJ_FIELD_LIST_SIZE_GE,
+				MEDIA, "uploadfile.links", 1, links.size()));
+		assertTrue(Iterables.all(links, Predicates.or(
+				LinkPredicates.relEquals(Link.Rel.UPLOAD_DEFAULT),
+				LinkPredicates.relEquals(Link.Rel.UPLOAD_ALTERNATE))),
+				String.format(OBJ_FIELD_REQ, MEDIA, "uploadFile.links.first"));
+
+		Link uploadLink = Iterables.find(links,
+				LinkPredicates.relEquals(Link.Rel.UPLOAD_DEFAULT));
+		return uploadLink;
+	}
+
+	private Media addEmptyMediaInVDC(Vdc currentVDC, String keyPairName) {
+		Link addMedia = find(
+				currentVDC.getLinks(),
+				and(relEquals("add"), typeEquals(VCloudDirectorMediaType.MEDIA)));
+
+		Media sourceMedia = Media.builder().type(VCloudDirectorMediaType.MEDIA)
+				.name(keyPairName).size(0).imageType(Media.ImageType.ISO)
+				.description("iso generated as KeyPair bucket").build();
+
+		Media emptyMedia = mediaApi.add(addMedia.getHref(), sourceMedia);
+		Checks.checkMediaFor(MEDIA, emptyMedia);
+		return emptyMedia;
+	}
+
+	private String generateKeyPair(String keyPairName) {
+		Map<String, String> key = Maps.newHashMap();
+		key.put("keyName", keyPairName);
+		key.put("keyFingerprint", SshKeys.sha1PrivateKey(sshKey.get("private")));
+		key.put("publicKey", sshKey.get("public"));
+		return json.toJson(key);
+	}
+
+	private void setKeyPairOnkeyPairsContainer(Media media, String keyPairName,
+			String keyPair) {
+		Task setKeyPair = mediaApi.getMetadataApi(media.getId()).put(
+				keyPairName, keyPair);
+		Checks.checkTask(setKeyPair);
+		assertTrue(retryTaskSuccess.apply(setKeyPair),
+				String.format(TASK_COMPLETE_TIMELY, "setKeyPair"));
+	}
+}
diff --git a/labs/vcloud-director/src/test/java/org/jclouds/vcloud/director/v1_5/features/MediaApiExpectTest.java b/labs/vcloud-director/src/test/java/org/jclouds/vcloud/director/v1_5/features/MediaApiExpectTest.java
index 3fbe284..6a66301 100644
--- a/labs/vcloud-director/src/test/java/org/jclouds/vcloud/director/v1_5/features/MediaApiExpectTest.java
+++ b/labs/vcloud-director/src/test/java/org/jclouds/vcloud/director/v1_5/features/MediaApiExpectTest.java
@@ -33,7 +33,6 @@
 import org.jclouds.vcloud.director.v1_5.domain.Media.ImageType;
 import org.jclouds.vcloud.director.v1_5.domain.Metadata;
 import org.jclouds.vcloud.director.v1_5.domain.MetadataEntry;
-import org.jclouds.vcloud.director.v1_5.domain.MetadataValue;
 import org.jclouds.vcloud.director.v1_5.domain.Owner;
 import org.jclouds.vcloud.director.v1_5.domain.Reference;
 import org.jclouds.vcloud.director.v1_5.domain.Task;
@@ -259,7 +258,7 @@
       Metadata inputMetadata = metadata();
       Task expectedTask = mergeMetadataTask();
 
-      assertEquals(api.getMediaApi().getMetadataApi(mediaUri).merge(inputMetadata), expectedTask);
+      assertEquals(api.getMediaApi().getMetadataApi(mediaUri).putAll(inputMetadata), expectedTask);
    }
    
    public void testGetMetadataValue() {
@@ -273,11 +272,8 @@
             new VcloudHttpResponsePrimer()
                .xmlFilePayload("/media/metadataValue.xml", VCloudDirectorMediaType.METADATA_VALUE)
                .httpResponseBuilder().build());
-      
-      MetadataValue expected = metadataValue();
-      
-
-      assertEquals(api.getMediaApi().getMetadataApi(mediaUri).getValue("key"), expected);
+     
+      assertEquals(api.getMediaApi().getMetadataApi(mediaUri).get("key"), "value");
    }
    
    @Test
@@ -293,12 +289,10 @@
             new VcloudHttpResponsePrimer()
                .xmlFilePayload("/media/setMetadataValueTask.xml", VCloudDirectorMediaType.TASK)
                .httpResponseBuilder().build());
-      
-      MetadataValue inputMetadataValue = MetadataValue.builder().value("value").build();
-      
+            
       Task expectedTask = setMetadataEntryTask();
 
-      assertEquals(api.getMediaApi().getMetadataApi(mediaUri).putEntry("key", inputMetadataValue), expectedTask);
+      assertEquals(api.getMediaApi().getMetadataApi(mediaUri).put("key", "value"), expectedTask);
    }
    
    @Test
@@ -314,9 +308,9 @@
                .xmlFilePayload("/media/removeMetadataEntryTask.xml", VCloudDirectorMediaType.TASK)
                .httpResponseBuilder().build());
       
-      Task expectedTask = removeEntryTask();
+      Task expectedTask = removeTask();
 
-      assertEquals(api.getMediaApi().getMetadataApi(mediaUri).removeEntry("key"), expectedTask);
+      assertEquals(api.getMediaApi().getMetadataApi(mediaUri).remove("key"), expectedTask);
    }
    
    @Test
@@ -635,27 +629,6 @@
          .build();
    }
    
-   private static MetadataValue metadataValue() {
-      return MetadataValue.builder()
-            .type("application/vnd.vmware.vcloud.metadata.value+xml")
-            .href(URI.create("https://mycloud.greenhousedata.com/api/media/c93e5cdc-f29a-4749-8ed2-093df04cc75e/metadata/key"))
-            .link(Link.builder()
-               .rel("up")
-               .type("application/vnd.vmware.vcloud.metadata+xml")
-               .href(URI.create("https://mycloud.greenhousedata.com/api/media/c93e5cdc-f29a-4749-8ed2-093df04cc75e/metadata"))
-               .build())
-            .link(Link.builder()
-               .rel("edit")
-               .type("application/vnd.vmware.vcloud.metadata.value+xml")
-               .href(URI.create("https://mycloud.greenhousedata.com/api/media/c93e5cdc-f29a-4749-8ed2-093df04cc75e/metadata/key"))
-               .build())
-            .link(Link.builder()
-               .rel("remove")
-               .href(URI.create("https://mycloud.greenhousedata.com/api/media/c93e5cdc-f29a-4749-8ed2-093df04cc75e/metadata/key"))
-               .build())
-            .value("value").build();
-   }
-   
    private Task mergeMetadataTask() {
       return Task.builder()
          .status("running")
@@ -722,7 +695,7 @@
          .build();
    }
    
-   public static Task removeEntryTask() {
+   public static Task removeTask() {
       return Task.builder()
          .name("task")
          .id("urn:vcloud:task:c6dca927-eab4-41fa-ad6a-3ac58602541c")
diff --git a/labs/vcloud-director/src/test/java/org/jclouds/vcloud/director/v1_5/features/MediaApiLiveTest.java b/labs/vcloud-director/src/test/java/org/jclouds/vcloud/director/v1_5/features/MediaApiLiveTest.java
index 66d611d..6b7af00 100644
--- a/labs/vcloud-director/src/test/java/org/jclouds/vcloud/director/v1_5/features/MediaApiLiveTest.java
+++ b/labs/vcloud-director/src/test/java/org/jclouds/vcloud/director/v1_5/features/MediaApiLiveTest.java
@@ -27,7 +27,6 @@
 import static org.jclouds.vcloud.director.v1_5.VCloudDirectorLiveTestConstants.OBJ_DEL;
 import static org.jclouds.vcloud.director.v1_5.VCloudDirectorLiveTestConstants.OBJ_FIELD_ATTRB_DEL;
 import static org.jclouds.vcloud.director.v1_5.VCloudDirectorLiveTestConstants.OBJ_FIELD_CLONE;
-import static org.jclouds.vcloud.director.v1_5.VCloudDirectorLiveTestConstants.OBJ_FIELD_CONTAINS;
 import static org.jclouds.vcloud.director.v1_5.VCloudDirectorLiveTestConstants.OBJ_FIELD_EQ;
 import static org.jclouds.vcloud.director.v1_5.VCloudDirectorLiveTestConstants.OBJ_FIELD_LIST_SIZE_EQ;
 import static org.jclouds.vcloud.director.v1_5.VCloudDirectorLiveTestConstants.OBJ_FIELD_LIST_SIZE_GE;
@@ -55,8 +54,6 @@
 import org.jclouds.vcloud.director.v1_5.domain.Link;
 import org.jclouds.vcloud.director.v1_5.domain.Media;
 import org.jclouds.vcloud.director.v1_5.domain.Metadata;
-import org.jclouds.vcloud.director.v1_5.domain.MetadataEntry;
-import org.jclouds.vcloud.director.v1_5.domain.MetadataValue;
 import org.jclouds.vcloud.director.v1_5.domain.Owner;
 import org.jclouds.vcloud.director.v1_5.domain.Reference;
 import org.jclouds.vcloud.director.v1_5.domain.Task;
@@ -69,7 +66,7 @@
 import org.testng.annotations.Test;
 
 import com.google.common.base.Predicates;
-import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.Iterables;
 
 /**
@@ -95,7 +92,7 @@
    private Media media, oldMedia;
    private Owner owner;
    private Metadata metadata;
-   private MetadataValue metadataValue;
+   private String metadataValue;
    private String metadataEntryValue = "value";
 
    @Override
@@ -179,7 +176,7 @@
 
       owner = media.getOwner();
       assertNotNull(owner, String.format(OBJ_FIELD_REQ_LIVE, MEDIA, "owner"));
-      Checks.checkResourceType(media.getOwner());
+      Checks.checkResource(media.getOwner());
 
       Checks.checkMediaFor(MEDIA, media);
    }
@@ -193,7 +190,7 @@
                         directOwner.toString()));
 
       // parent type
-      Checks.checkResourceType(directOwner);
+      Checks.checkResource(directOwner);
 
       // required
       assertNotNull(directOwner.getUser(), String.format(OBJ_FIELD_REQ, "Owner", "user"));
@@ -223,7 +220,7 @@
       assertTrue(media.clone(oldMedia),
                String.format(OBJ_FIELD_CLONE, MEDIA, "copied media", media.toString(), oldMedia.toString()));
 
-      mediaApi.getMetadataApi(media.getId()).putEntry("key", MetadataValue.builder().value("value").build());
+      mediaApi.getMetadataApi(media.getId()).put("key", "value");
 
       media = vdcApi
                .cloneMedia(vdcUrn, CloneMediaParams.builder().source(Reference.builder().fromEntity(media).build())
@@ -286,83 +283,59 @@
    @Test(description = "POST /media/{id}/metadata", dependsOnMethods = { "testGetMedia" })
    public void testMergeMetadata() {
       // test new
-      Set<MetadataEntry> inputEntries = ImmutableSet.of(MetadataEntry.builder().entry("testKey", "testValue").build());
-      Metadata inputMetadata = Metadata.builder().entries(inputEntries).build();
-
-      Task mergeMetadata = mediaApi.getMetadataApi(media.getId()).merge(inputMetadata);
+      Task mergeMetadata = mediaApi.getMetadataApi(media.getId()).putAll(ImmutableMap.of("testKey", "testValue"));
       Checks.checkTask(mergeMetadata);
       assertTrue(retryTaskSuccess.apply(mergeMetadata), String.format(TASK_COMPLETE_TIMELY, "mergeMetadata(new)"));
       metadata = mediaApi.getMetadataApi(media.getId()).get();
       Checks.checkMetadataFor(MEDIA, metadata);
-      checkMetadataContainsEntries(metadata, inputEntries);
+      assertEquals(metadata.get("testKey"), "testValue");
 
       media = mediaApi.get(media.getId());
       Checks.checkMediaFor(MEDIA, media);
 
       // test edit
-      inputEntries = ImmutableSet.of(MetadataEntry.builder().entry("testKey", "new testValue").build());
-      inputMetadata = Metadata.builder().entries(inputEntries).build();
-
-      mergeMetadata = mediaApi.getMetadataApi(media.getId()).merge(inputMetadata);
+      mergeMetadata = mediaApi.getMetadataApi(media.getId()).put("testKey", "new testValue");
       Checks.checkTask(mergeMetadata);
       assertTrue(retryTaskSuccess.apply(mergeMetadata), String.format(TASK_COMPLETE_TIMELY, "mergeMetadata(edit)"));
       metadata = mediaApi.getMetadataApi(media.getId()).get();
       Checks.checkMetadataFor(MEDIA, metadata);
-      checkMetadataContainsEntries(metadata, inputEntries);
+      assertEquals(metadata.get("testKey"), "new testValue");
 
       media = mediaApi.get(media.getId());
       Checks.checkMediaFor(MEDIA, media);
    }
 
-   private void checkMetadataContainsEntries(Metadata metadata, Set<MetadataEntry> entries) {
-      for (MetadataEntry inputEntry : entries) {
-         boolean found = false;
-         for (MetadataEntry entry : metadata.getMetadataEntries()) {
-            if (equal(inputEntry.getKey(), entry.getKey())) {
-               found = true;
-               break;
-            }
-         }
-
-         if (!found) {
-            String.format(OBJ_FIELD_CONTAINS, MEDIA, "metadata", Iterables.toString(metadata.getMetadataEntries()),
-                     Iterables.toString(entries));
-         }
-      }
-   }
-
    @Test(description = "GET /media/{id}/metadata/{key}", dependsOnMethods = { "testSetMetadataValue" })
    public void testGetMetadataValue() {
-      metadataValue = mediaApi.getMetadataApi(media.getId()).getValue("key");
-      Checks.checkMetadataValueFor(MEDIA, metadataValue);
+      metadataValue = mediaApi.getMetadataApi(media.getId()).get("key");
+      assertNotNull(metadataValue);
    }
 
    @Test(description = "PUT /media/{id}/metadata/{key}", dependsOnMethods = { "testMergeMetadata" })
    public void testSetMetadataValue() {
       metadataEntryValue = "value";
-      MetadataValue newValue = MetadataValue.builder().value(metadataEntryValue).build();
-
-      Task setMetadataEntry = mediaApi.getMetadataApi(media.getId()).putEntry("key", newValue);
+      
+      Task setMetadataEntry = mediaApi.getMetadataApi(media.getId()).put("key", metadataEntryValue);
       Checks.checkTask(setMetadataEntry);
       assertTrue(retryTaskSuccess.apply(setMetadataEntry), String.format(TASK_COMPLETE_TIMELY, "setMetadataEntry"));
-      metadataValue = mediaApi.getMetadataApi(media.getId()).getValue("key");
-      Checks.checkMetadataValueFor(MEDIA, metadataValue);
+      metadataValue = mediaApi.getMetadataApi(media.getId()).get("key");
+      assertNotNull(metadataValue);
    }
 
    @Test(description = "DELETE /media/{id}/metadata/{key}", dependsOnMethods = { "testGetMetadata",
             "testGetMetadataValue" })
    public void testRemoveMetadata() {
-      Task removeEntry = mediaApi.getMetadataApi(media.getId()).removeEntry("testKey");
-      Checks.checkTask(removeEntry);
-      assertTrue(retryTaskSuccess.apply(removeEntry), String.format(TASK_COMPLETE_TIMELY, "removeEntry"));
+      Task remove = mediaApi.getMetadataApi(media.getId()).remove("testKey");
+      Checks.checkTask(remove);
+      assertTrue(retryTaskSuccess.apply(remove), String.format(TASK_COMPLETE_TIMELY, "remove"));
 
-      metadataValue = mediaApi.getMetadataApi(media.getId()).getValue("testKey");
+      metadataValue = mediaApi.getMetadataApi(media.getId()).get("testKey");
       assertNull(metadataValue, String.format(OBJ_FIELD_ATTRB_DEL, MEDIA, "Metadata",
                metadataValue != null ? metadataValue.toString() : "", "MetadataEntry",
                metadataValue != null ? metadataValue.toString() : ""));
 
-      metadataValue = mediaApi.getMetadataApi(media.getId()).getValue("key");
-      Checks.checkMetadataValueFor(MEDIA, metadataValue);
+      metadataValue = mediaApi.getMetadataApi(media.getId()).get("key");
+      assertNotNull(metadataValue);
 
       media = mediaApi.get(media.getId());
       Checks.checkMediaFor(MEDIA, media);
diff --git a/labs/vcloud-director/src/test/java/org/jclouds/vcloud/director/v1_5/features/NetworkApiExpectTest.java b/labs/vcloud-director/src/test/java/org/jclouds/vcloud/director/v1_5/features/NetworkApiExpectTest.java
index 5458c81..2cd1038 100644
--- a/labs/vcloud-director/src/test/java/org/jclouds/vcloud/director/v1_5/features/NetworkApiExpectTest.java
+++ b/labs/vcloud-director/src/test/java/org/jclouds/vcloud/director/v1_5/features/NetworkApiExpectTest.java
@@ -38,7 +38,6 @@
 import org.jclouds.vcloud.director.v1_5.domain.Link;
 import org.jclouds.vcloud.director.v1_5.domain.Metadata;
 import org.jclouds.vcloud.director.v1_5.domain.MetadataEntry;
-import org.jclouds.vcloud.director.v1_5.domain.MetadataValue;
 import org.jclouds.vcloud.director.v1_5.domain.network.DhcpService;
 import org.jclouds.vcloud.director.v1_5.domain.network.IpAddresses;
 import org.jclouds.vcloud.director.v1_5.domain.network.IpRange;
@@ -216,22 +215,9 @@
    @Test
    public void testGetNetworkMetadataEntryHref() {
       VCloudDirectorApi api = requestsSendResponses(loginRequest, sessionResponse, getMetadataValue, getMetadataValueResponse);
-      assertEquals(api.getNetworkApi().getMetadataApi(networkHref).getValue("KEY"), metadataValue());
+      assertEquals(api.getNetworkApi().getMetadataApi(networkHref).get("KEY"), "value");
    }
    
-   private MetadataValue metadataValue() {
-      return MetadataValue.builder()
-               .href(URI.create("https://vcloudbeta.bluelock.com/api/network/55a677cf-ab3f-48ae-b880-fab90421980c/metadata/key"))
-               .link(Link.builder()
-                  .rel("up")
-                  .type("application/vnd.vmware.vcloud.metadata+xml")
-                  .href(URI.create("https://vcloudbeta.bluelock.com/api/network/55a677cf-ab3f-48ae-b880-fab90421980c/metadata"))
-                  .build())
-               .value("value")
-               .build();
-   }
-
-
    public static OrgNetwork network() {
       return OrgNetwork.builder()
          .name("ilsolation01-Jclouds")
diff --git a/labs/vcloud-director/src/test/java/org/jclouds/vcloud/director/v1_5/features/NetworkApiLiveTest.java b/labs/vcloud-director/src/test/java/org/jclouds/vcloud/director/v1_5/features/NetworkApiLiveTest.java
index 40dc0f0..76af7d9 100644
--- a/labs/vcloud-director/src/test/java/org/jclouds/vcloud/director/v1_5/features/NetworkApiLiveTest.java
+++ b/labs/vcloud-director/src/test/java/org/jclouds/vcloud/director/v1_5/features/NetworkApiLiveTest.java
@@ -24,7 +24,7 @@
 import static org.jclouds.vcloud.director.v1_5.VCloudDirectorLiveTestConstants.OBJ_REQ_LIVE;
 import static org.jclouds.vcloud.director.v1_5.VCloudDirectorLiveTestConstants.REQUIRED_VALUE_OBJECT_FMT;
 import static org.jclouds.vcloud.director.v1_5.VCloudDirectorLiveTestConstants.URN_REQ_LIVE;
-import static org.jclouds.vcloud.director.v1_5.domain.Checks.checkResourceType;
+import static org.jclouds.vcloud.director.v1_5.domain.Checks.checkResource;
 import static org.testng.Assert.assertEquals;
 import static org.testng.Assert.assertFalse;
 import static org.testng.Assert.assertNotNull;
@@ -33,7 +33,6 @@
 import org.jclouds.vcloud.director.v1_5.domain.Checks;
 import org.jclouds.vcloud.director.v1_5.domain.Metadata;
 import org.jclouds.vcloud.director.v1_5.domain.MetadataEntry;
-import org.jclouds.vcloud.director.v1_5.domain.MetadataValue;
 import org.jclouds.vcloud.director.v1_5.domain.Task;
 import org.jclouds.vcloud.director.v1_5.domain.network.Network;
 import org.jclouds.vcloud.director.v1_5.domain.org.OrgNetwork;
@@ -71,7 +70,7 @@
    public void cleanUp() {
       if (metadataSet) {
          try {
-            Task remove = adminContext.getApi().getNetworkApi().getMetadataApi(networkUrn).removeEntry("key");
+            Task remove = adminContext.getApi().getNetworkApi().getMetadataApi(networkUrn).remove("key");
             taskDoneEventually(remove);
          } catch (Exception e) {
             logger.warn(e, "Error when deleting metadata");
@@ -95,8 +94,8 @@
    }
 
    private void setupMetadata() {
-      adminContext.getApi().getNetworkApi().getMetadataApi(networkUrn)
-               .putEntry("key", MetadataValue.builder().value("value").build());
+      //TODO: block until complete
+      adminContext.getApi().getNetworkApi().getMetadataApi(networkUrn).put("key", "value");
       metadataSet = true;
    }
 
@@ -112,7 +111,7 @@
                String.format(OBJ_FIELD_REQ_LIVE, NETWORK, "metadata.entries"));
 
       // parent type
-      checkResourceType(metadata);
+      checkResource(metadata);
 
       for (MetadataEntry entry : metadata.getMetadataEntries()) {
          // required elements and attributes
@@ -122,21 +121,14 @@
                   String.format(OBJ_FIELD_ATTRB_REQ, networkApi, "MetadataEntry", entry.getValue(), "value"));
 
          // parent type
-         checkResourceType(entry);
+         checkResource(entry);
       }
    }
 
    @Test(description = "GET /network/{id}/metadata/{key}", dependsOnMethods = { "testGetMetadata" })
    public void testGetMetadataValue() {
-      MetadataValue metadataValue = networkApi.getMetadataApi(networkUrn).getValue("key");
+      String metadataValue = networkApi.getMetadataApi(networkUrn).get("key");
 
-      // Check parent type
-      checkResourceType(metadataValue);
-
-      // Check required elements and attributes
-      String value = metadataValue.getValue();
-      assertNotNull(value,
-               String.format(OBJ_FIELD_ATTRB_REQ, NETWORK, "MetadataEntry", metadataValue.toString(), "value"));
-      assertEquals(value, "value", String.format(OBJ_FIELD_EQ, NETWORK, "metadataEntry.value", "value", value));
+      assertEquals(metadataValue, "value", String.format(OBJ_FIELD_EQ, NETWORK, "metadataEntry.value", "value", metadataValue));
    }
 }
diff --git a/labs/vcloud-director/src/test/java/org/jclouds/vcloud/director/v1_5/features/OrgApiExpectTest.java b/labs/vcloud-director/src/test/java/org/jclouds/vcloud/director/v1_5/features/OrgApiExpectTest.java
index 06c6727..2beadb0 100644
--- a/labs/vcloud-director/src/test/java/org/jclouds/vcloud/director/v1_5/features/OrgApiExpectTest.java
+++ b/labs/vcloud-director/src/test/java/org/jclouds/vcloud/director/v1_5/features/OrgApiExpectTest.java
@@ -33,7 +33,6 @@
 import org.jclouds.vcloud.director.v1_5.domain.Link;
 import org.jclouds.vcloud.director.v1_5.domain.Metadata;
 import org.jclouds.vcloud.director.v1_5.domain.MetadataEntry;
-import org.jclouds.vcloud.director.v1_5.domain.MetadataValue;
 import org.jclouds.vcloud.director.v1_5.domain.Reference;
 import org.jclouds.vcloud.director.v1_5.domain.org.Org;
 import org.jclouds.vcloud.director.v1_5.domain.org.OrgList;
@@ -179,7 +178,7 @@
    @Test
    public void testGetOrgMetadataEntryHref() {
       VCloudDirectorApi api = requestsSendResponses(loginRequest, sessionResponse, getMetadataValue, getMetadataValueResponse);
-      assertEquals(api.getOrgApi().getMetadataApi(orgHref).getValue("KEY"), metadataValue());
+      assertEquals(api.getOrgApi().getMetadataApi(orgHref).get("KEY"), "VALUE");
    }
    
    public static Org org() {
@@ -243,16 +242,4 @@
             .entry("KEY", "VALUE")
             .build();
    }
-   
-   public static MetadataValue metadataValue() {
-      return MetadataValue.builder()
-            .href(URI.create("https://vcloudbeta.bluelock.com/api/org/6f312e42-cd2b-488d-a2bb-97519cd57ed0/metadata/KEY"))
-            .link(Link.builder()
-                  .rel("up")
-                  .type("application/vnd.vmware.vcloud.metadata+xml")
-                  .href(URI.create("https://vcloudbeta.bluelock.com/api/org/6f312e42-cd2b-488d-a2bb-97519cd57ed0/metadata"))
-                  .build())
-            .value("VALUE")
-            .build();
-   }
 }
diff --git a/labs/vcloud-director/src/test/java/org/jclouds/vcloud/director/v1_5/features/OrgApiLiveTest.java b/labs/vcloud-director/src/test/java/org/jclouds/vcloud/director/v1_5/features/OrgApiLiveTest.java
index 050e814..11483c7 100644
--- a/labs/vcloud-director/src/test/java/org/jclouds/vcloud/director/v1_5/features/OrgApiLiveTest.java
+++ b/labs/vcloud-director/src/test/java/org/jclouds/vcloud/director/v1_5/features/OrgApiLiveTest.java
@@ -22,7 +22,6 @@
 import static org.jclouds.vcloud.director.v1_5.VCloudDirectorLiveTestConstants.CORRECT_VALUE_OBJECT_FMT;
 import static org.jclouds.vcloud.director.v1_5.VCloudDirectorLiveTestConstants.NOT_EMPTY_OBJECT_FMT;
 import static org.jclouds.vcloud.director.v1_5.domain.Checks.checkMetadata;
-import static org.jclouds.vcloud.director.v1_5.domain.Checks.checkMetadataValue;
 import static org.jclouds.vcloud.director.v1_5.domain.Checks.checkOrg;
 import static org.jclouds.vcloud.director.v1_5.domain.Checks.checkReferenceType;
 import static org.testng.Assert.assertEquals;
@@ -32,7 +31,6 @@
 import org.jclouds.vcloud.director.v1_5.VCloudDirectorMediaType;
 import org.jclouds.vcloud.director.v1_5.domain.AdminCatalog;
 import org.jclouds.vcloud.director.v1_5.domain.Metadata;
-import org.jclouds.vcloud.director.v1_5.domain.MetadataValue;
 import org.jclouds.vcloud.director.v1_5.domain.Reference;
 import org.jclouds.vcloud.director.v1_5.domain.Task;
 import org.jclouds.vcloud.director.v1_5.domain.org.OrgList;
@@ -67,7 +65,7 @@
    public void cleanUp() throws Exception {
       if (adminMembersSet) {
          try {
-            Task remove = adminContext.getApi().getOrgApi().getMetadataApi(orgUrn).removeEntry("KEY");
+            Task remove = adminContext.getApi().getOrgApi().getMetadataApi(orgUrn).remove("KEY");
             taskDoneEventually(remove);
          } catch (Exception e) {
             logger.warn(e, "Error when deleting metadata entry");
@@ -79,7 +77,7 @@
          }
       }
    }
-
+   
    /*
     * Shared state between dependent tests.
     */
@@ -126,8 +124,8 @@
     * the need for configuration
     */
    private void setupAdminMembers() {
-      adminContext.getApi().getOrgApi().getMetadataApi(orgUrn)
-               .putEntry("KEY", MetadataValue.builder().value("VALUE").build());
+      //TODO: block until complete
+      adminContext.getApi().getOrgApi().getMetadataApi(orgUrn).put("KEY", "VALUE");
 
       AdminCatalog newCatalog = AdminCatalog.builder().name("Test Catalog " + getTestDateTimeStamp())
                .description("created by testOrg()").build();
@@ -156,16 +154,14 @@
    @Test(description = "GET /org/{id}/metadata/{key}", dependsOnMethods = { "testGetOrgMetadata" })
    public void testGetOrgMetadataValue() {
       // Call the method being tested
-      MetadataValue value = orgApi.getMetadataApi(orgUrn).getValue("KEY");
+      String value = orgApi.getMetadataApi(orgUrn).get("KEY");
 
       // NOTE The environment MUST have configured the metadata entry as '{ key="KEY", value="VALUE"
       // )'
 
       String expected = "VALUE";
 
-      checkMetadataValue(value);
-      assertEquals(value.getValue(), expected,
-               String.format(CORRECT_VALUE_OBJECT_FMT, "Value", "MetadataValue", expected, value.getValue()));
+      assertEquals(value, expected, String.format(CORRECT_VALUE_OBJECT_FMT, "Value", "MetadataValue", expected, value));
    }
 
 }
diff --git a/labs/vcloud-director/src/test/java/org/jclouds/vcloud/director/v1_5/features/QueryApiLiveTest.java b/labs/vcloud-director/src/test/java/org/jclouds/vcloud/director/v1_5/features/QueryApiLiveTest.java
index efccc33..b66b28f 100644
--- a/labs/vcloud-director/src/test/java/org/jclouds/vcloud/director/v1_5/features/QueryApiLiveTest.java
+++ b/labs/vcloud-director/src/test/java/org/jclouds/vcloud/director/v1_5/features/QueryApiLiveTest.java
@@ -26,7 +26,6 @@
 import java.net.URI;
 import java.util.Arrays;
 import java.util.Collection;
-import java.util.Collections;
 import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Set;
@@ -49,6 +48,7 @@
 import org.testng.annotations.BeforeClass;
 import org.testng.annotations.Test;
 
+import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.Iterables;
 
 /**
@@ -79,6 +79,8 @@
    public void setupRequiredApis() {
       queryApi = context.getApi().getQueryApi();
       vAppApi = context.getApi().getVAppApi();
+      
+      cleanUpVAppTemplateInOrg();
    }
 
    @Test(description = "GET /query")
@@ -134,7 +136,6 @@
    @Test(description = "GET /vApps/query")
    public void testQueryAllVApps() {
       vApp = instantiateVApp();
-
       QueryResultRecords queryResult = queryApi.vAppsQueryAll();
       Set<URI> hrefs = toHrefs(queryResult);
 
@@ -143,15 +144,21 @@
                + "; but only has " + hrefs);
    }
 
-   @Test(description = "GET /vApps/query?filter", dependsOnMethods = { "testQueryAllVApps" })
-   public void testQueryVAppsWithFilter() {
-      QueryResultRecords queryResult = queryApi.vAppsQuery(String.format("name==%s", vApp.getName()));
-      Set<URI> hrefs = toHrefs(queryResult);
+	@Test(description = "GET /vApps/query?filter", dependsOnMethods = { "testQueryAllVApps" })
+	public void testQueryVAppsWithFilter() {
+		QueryResultRecords queryResult = queryApi.vAppsQuery(String.format(
+				"name==%s", vApp.getName()));
+		Set<URI> hrefs = toHrefs(queryResult);
 
-      assertRecordTypes(queryResult, Arrays.asList(VCloudDirectorMediaType.VAPP, null), QueryResultVAppRecord.class);
-      assertEquals(hrefs, Collections.singleton(vApp.getHref()),
-               "VApps query result should have found vApp " + vApp.getHref());
-   }
+		assertRecordTypes(queryResult,
+				Arrays.asList(VCloudDirectorMediaType.VAPP, null),
+				QueryResultVAppRecord.class);
+		String message = "VApps query result should have found vApp "
+				+ vApp.getHref();
+		assertTrue(
+				ImmutableSet.copyOf(hrefs).equals(
+						ImmutableSet.of(vApp.getHref())), message);
+	}
 
    @Test(description = "GET /vms/query", dependsOnMethods = { "testQueryAllVApps" })
    public void testQueryAllVms() {
@@ -178,18 +185,24 @@
                + hrefs);
    }
 
-   @Test(description = "GET /vms/query?filter", dependsOnMethods = { "testQueryAllVms" })
-   public void testQueryAllVmsWithFilter() {
-      List<Vm> vms = vApp.getChildren().getVms();
-      Set<URI> vmHrefs = toHrefs(vms);
+	@Test(description = "GET /vms/query?filter", dependsOnMethods = { "testQueryAllVms" })
+	public void testQueryAllVmsWithFilter() {
+		List<Vm> vms = vApp.getChildren().getVms();
+		Set<URI> vmHrefs = toHrefs(vms);
 
-      QueryResultRecords queryResult = queryApi.vmsQuery(String.format("containerName==%s", vApp.getName()));
-      Set<URI> hrefs = toHrefs(queryResult);
+		QueryResultRecords queryResult = queryApi.vmsQuery(String.format(
+				"containerName==%s", vApp.getName()));
+		Set<URI> hrefs = toHrefs(queryResult);
 
-      assertRecordTypes(queryResult, Arrays.asList(VCloudDirectorMediaType.VM, null), QueryResultVMRecord.class);
-      assertEquals(hrefs, vmHrefs, "VMs query result should equal vms of vApp " + vApp.getName() + " (" + vmHrefs
-               + "); but only has " + hrefs);
-   }
+		assertRecordTypes(queryResult,
+				Arrays.asList(VCloudDirectorMediaType.VM, null),
+				QueryResultVMRecord.class);
+		String message = "VMs query result should equal vms of vApp "
+				+ vApp.getName() + " (" + vmHrefs + "); but only has " + hrefs;
+		assertTrue(
+				ImmutableSet.copyOf(hrefs).equals(ImmutableSet.copyOf(vmHrefs)),
+				message);
+	}
 
    @Test(description = "GET /mediaList/query")
    public void testQueryAllMedia() {
@@ -231,4 +244,5 @@
       }
       return hrefs;
    }
+     
 }
diff --git a/labs/vcloud-director/src/test/java/org/jclouds/vcloud/director/v1_5/features/VAppApiLiveTest.java b/labs/vcloud-director/src/test/java/org/jclouds/vcloud/director/v1_5/features/VAppApiLiveTest.java
index 49030f6..131982c 100644
--- a/labs/vcloud-director/src/test/java/org/jclouds/vcloud/director/v1_5/features/VAppApiLiveTest.java
+++ b/labs/vcloud-director/src/test/java/org/jclouds/vcloud/director/v1_5/features/VAppApiLiveTest.java
@@ -31,8 +31,6 @@
 import static org.jclouds.vcloud.director.v1_5.domain.Checks.checkMetadata;
 import static org.jclouds.vcloud.director.v1_5.domain.Checks.checkMetadataFor;
 import static org.jclouds.vcloud.director.v1_5.domain.Checks.checkMetadataKeyAbsentFor;
-import static org.jclouds.vcloud.director.v1_5.domain.Checks.checkMetadataValue;
-import static org.jclouds.vcloud.director.v1_5.domain.Checks.checkMetadataValueFor;
 import static org.jclouds.vcloud.director.v1_5.domain.Checks.checkNetworkConfigSection;
 import static org.jclouds.vcloud.director.v1_5.domain.Checks.checkNetworkSection;
 import static org.jclouds.vcloud.director.v1_5.domain.Checks.checkOwner;
@@ -59,8 +57,6 @@
 import org.jclouds.vcloud.director.v1_5.domain.AccessSetting;
 import org.jclouds.vcloud.director.v1_5.domain.Checks;
 import org.jclouds.vcloud.director.v1_5.domain.Metadata;
-import org.jclouds.vcloud.director.v1_5.domain.MetadataEntry;
-import org.jclouds.vcloud.director.v1_5.domain.MetadataValue;
 import org.jclouds.vcloud.director.v1_5.domain.Owner;
 import org.jclouds.vcloud.director.v1_5.domain.ProductSectionList;
 import org.jclouds.vcloud.director.v1_5.domain.Reference;
@@ -114,10 +110,9 @@
  * 
  * @author grkvlt@apache.org
  */
-@Test(groups = { "live", "user" }, singleThreaded = true, testName = "VAppApiLiveTest")
+@Test(singleThreaded = true, testName = "VAppApiLiveTest")
 public class VAppApiLiveTest extends AbstractVAppApiLiveTest {
 
-   private MetadataValue metadataValue;
    private String key;
    private boolean testUserCreated = false;
    private User user;
@@ -146,7 +141,7 @@
    /**
     * @see VAppApi#get(URI)
     */
-   @Test(description = "GET /vApp/{id}")
+   @Test(groups = { "live", "user" }, description = "GET /vApp/{id}")
    public void testGetVApp() {
       // The method under test
       vApp = vAppApi.get(vAppUrn);
@@ -169,7 +164,7 @@
       assertVAppStatus(vAppUrn, Status.POWERED_OFF);
    }
 
-   @Test(description = "POST /vApp/{id}/action/recomposeVApp")
+   @Test(groups = { "live", "user" }, description = "POST /vApp/{id}/action/recomposeVApp")
    public void testRecomposeVApp() {
       
       VApp composedVApp = vdcApi.composeVApp(vdcUrn, ComposeVAppParams.builder()
@@ -227,7 +222,7 @@
    /**
     * @see VAppApi#edit(URI, VApp)
     */
-   @Test(description = "PUT /vApp/{id}", dependsOnMethods = { "testGetVApp" })
+   @Test(groups = { "live", "user" }, description = "PUT /vApp/{id}", dependsOnMethods = { "testGetVApp" })
    public void testEditVApp() {
       VApp newVApp = VApp.builder().name(name("new-name-")).description("New Description").build();
       vAppNames.add(newVApp.getName());
@@ -246,7 +241,7 @@
                String.format(OBJ_FIELD_EQ, VAPP, "Description", newVApp.getDescription(), vApp.getDescription()));
    }
 
-   @Test(description = "POST /vApp/{id}/action/deploy", dependsOnMethods = { "testGetVApp" })
+   @Test(groups = { "live", "user" }, description = "POST /vApp/{id}/action/deploy", dependsOnMethods = { "testGetVApp" })
    public void testDeployVApp() {
       DeployVAppParams params = DeployVAppParams.builder()
                .deploymentLeaseSeconds((int) TimeUnit.SECONDS.convert(1L, TimeUnit.HOURS)).notForceCustomization()
@@ -266,7 +261,7 @@
       assertVAppStatus(vAppUrn, Status.POWERED_OFF);
    }
 
-   @Test(description = "POST /vApp/{id}/power/action/powerOn", dependsOnMethods = { "testDeployVApp" })
+   @Test(groups = { "live", "user" }, description = "POST /vApp/{id}/power/action/powerOn", dependsOnMethods = { "testDeployVApp" })
    public void testPowerOnVApp() {
       // Power off VApp
       vApp = powerOffVApp(vAppUrn);
@@ -282,7 +277,7 @@
       assertVAppStatus(vAppUrn, Status.POWERED_ON);
    }
 
-   @Test(description = "POST /vApp/{id}/power/action/reboot", dependsOnMethods = { "testDeployVApp" })
+   @Test(groups = { "live", "user" }, description = "POST /vApp/{id}/power/action/reboot", dependsOnMethods = { "testDeployVApp" })
    public void testReboot() {
       // Power on VApp
       vApp = powerOnVApp(vAppUrn);
@@ -298,7 +293,7 @@
       assertVAppStatus(vAppUrn, Status.POWERED_OFF);
    }
 
-   @Test(description = "POST /vApp/{id}/power/action/shutdown", dependsOnMethods = { "testDeployVApp" })
+   @Test(groups = { "live", "user" }, description = "POST /vApp/{id}/power/action/shutdown", dependsOnMethods = { "testDeployVApp" })
    public void testShutdown() {
       // Power on VApp
       vApp = powerOnVApp(vAppUrn);
@@ -319,7 +314,7 @@
       vApp = powerOnVApp(vAppUrn);
    }
 
-   @Test(description = "POST /vApp/{id}/power/action/suspend", dependsOnMethods = { "testDeployVApp" })
+   @Test(groups = { "live", "user" }, description = "POST /vApp/{id}/power/action/suspend", dependsOnMethods = { "testDeployVApp" })
    public void testSuspend() {
       // Power on VApp
       vApp = powerOnVApp(vAppUrn);
@@ -338,7 +333,7 @@
       vApp = powerOnVApp(vAppUrn);
    }
 
-   @Test(description = "POST /vApp/{id}/power/action/reset", dependsOnMethods = { "testDeployVApp" })
+   @Test(groups = { "live", "user" }, description = "POST /vApp/{id}/power/action/reset", dependsOnMethods = { "testDeployVApp" })
    public void testReset() {
       // Power on VApp
       vApp = powerOnVApp(vAppUrn);
@@ -354,7 +349,7 @@
       assertVAppStatus(vAppUrn, Status.POWERED_ON);
    }
 
-   @Test(description = "POST /vApp/{id}/action/undeploy", dependsOnMethods = { "testDeployVApp" })
+   @Test(groups = { "live", "user" }, description = "POST /vApp/{id}/action/undeploy", dependsOnMethods = { "testDeployVApp" })
    public void testUndeployVApp() {
       // Power on VApp
       vApp = powerOnVApp(vAppUrn);
@@ -374,7 +369,7 @@
       assertVAppStatus(vAppUrn, Status.POWERED_OFF);
    }
 
-   @Test(description = "POST /vApp/{id}/power/action/powerOff", dependsOnMethods = { "testUndeployVApp" })
+   @Test(groups = { "live", "user" }, description = "POST /vApp/{id}/power/action/powerOff", dependsOnMethods = { "testUndeployVApp" })
    public void testPowerOffVApp() {
       // Power on VApp
       vApp = powerOnVApp(vAppUrn);
@@ -390,7 +385,7 @@
       assertVAppStatus(vAppUrn, Status.POWERED_OFF);
    }
 
-   @Test(description = "POST /vApp/{id}/action/controlAccess", dependsOnMethods = { "testGetVApp" })
+   @Test(groups = { "live", "user" }, description = "POST /vApp/{id}/action/controlAccess", dependsOnMethods = { "testGetVApp" })
    public void testControlAccessUser() {
       ControlAccessParams params = ControlAccessParams
                .builder()
@@ -409,7 +404,7 @@
       assertEquals(modified, params, String.format(ENTITY_EQUAL, "ControlAccessParams"));
    }
 
-   @Test(description = "POST /vApp/{id}/action/controlAccess", dependsOnMethods = { "testControlAccessUser" })
+   @Test(groups = { "live", "user" }, description = "POST /vApp/{id}/action/controlAccess", dependsOnMethods = { "testControlAccessUser" })
    public void testControlAccessEveryone() {
 
       ControlAccessParams params = ControlAccessParams.builder().sharedToEveryone().everyoneAccessLevel("FullControl")
@@ -425,7 +420,7 @@
       assertEquals(modified, params, String.format(ENTITY_EQUAL, "ControlAccessParams"));
    }
 
-   @Test(description = "POST /vApp/{id}/action/discardSuspendedState", dependsOnMethods = { "testDeployVApp" })
+   @Test(groups = { "live", "user" }, description = "POST /vApp/{id}/action/discardSuspendedState", dependsOnMethods = { "testDeployVApp" })
    public void testDiscardSuspendedState() {
       // Power on, then suspend the VApp
       vApp = powerOnVApp(vAppUrn);
@@ -437,58 +432,7 @@
                String.format(TASK_COMPLETE_TIMELY, "discardSuspendedState"));
    }
 
-   @Test(description = "POST /vApp/{id}/action/enterMaintenanceMode", groups = { "systemAdmin" })
-   public void testEnterMaintenanceMode() {
-
-      // Do this to a new vApp, so don't mess up subsequent tests by making the vApp read-only
-      VApp temp = instantiateVApp();
-      DeployVAppParams params = DeployVAppParams.builder()
-               .deploymentLeaseSeconds((int) TimeUnit.SECONDS.convert(1L, TimeUnit.HOURS)).notForceCustomization()
-               .notPowerOn().build();
-      Task deployVApp = vAppApi.deploy(temp.getId(), params);
-      assertTaskSucceedsLong(deployVApp);
-
-      try {
-         // Method under test
-         vAppApi.enterMaintenanceMode(temp.getId());
-
-         temp = vAppApi.get(temp.getId());
-         assertTrue(temp.isInMaintenanceMode(),
-                  String.format(CONDITION_FMT, "InMaintenanceMode", "TRUE", temp.isInMaintenanceMode()));
-
-         // Exit maintenance mode
-         vAppApi.exitMaintenanceMode(temp.getId());
-      } finally {
-         cleanUpVApp(temp);
-      }
-   }
-
-   @Test(description = "POST /vApp/{id}/action/exitMaintenanceMode", dependsOnMethods = { "testEnterMaintenanceMode" }, groups = { "systemAdmin" })
-   public void testExitMaintenanceMode() {
-      // Do this to a new vApp, so don't mess up subsequent tests by making the vApp read-only
-      VApp temp = instantiateVApp();
-      DeployVAppParams params = DeployVAppParams.builder()
-               .deploymentLeaseSeconds((int) TimeUnit.SECONDS.convert(1L, TimeUnit.HOURS)).notForceCustomization()
-               .notPowerOn().build();
-      Task deployVApp = vAppApi.deploy(temp.getId(), params);
-      assertTaskSucceedsLong(deployVApp);
-
-      try {
-         // Enter maintenance mode
-         vAppApi.enterMaintenanceMode(temp.getId());
-
-         // Method under test
-         vAppApi.exitMaintenanceMode(temp.getId());
-
-         temp = vAppApi.get(temp.getId());
-         assertFalse(temp.isInMaintenanceMode(),
-                  String.format(CONDITION_FMT, "InMaintenanceMode", "FALSE", temp.isInMaintenanceMode()));
-      } finally {
-         cleanUpVApp(temp);
-      }
-   }
-
-   @Test(description = "GET /vApp/{id}/controlAccess", dependsOnMethods = { "testGetVApp" })
+   @Test(groups = { "live", "user" }, description = "GET /vApp/{id}/controlAccess", dependsOnMethods = { "testGetVApp" })
    public void testGetControlAccess() {
       // The method under test
       ControlAccessParams controlAccess = vAppApi.getAccessControl(vAppUrn);
@@ -506,7 +450,7 @@
       checkLeaseSettingsSection(section);
    }
 
-   @Test(description = "PUT /vApp/{id}/leaseSettingsSection", dependsOnMethods = { "testGetLeaseSettingsSection" })
+   @Test(groups = { "live", "user" }, description = "PUT /vApp/{id}/leaseSettingsSection", dependsOnMethods = { "testGetLeaseSettingsSection" })
    public void testEditLeaseSettingsSection() {
       // Copy existing section
       LeaseSettingsSection oldSection = vAppApi.getLeaseSettingsSection(vAppUrn);
@@ -551,7 +495,7 @@
       assertEquals(modified, newSection, String.format(ENTITY_EQUAL, "LeaseSettingsSection"));
    }
 
-   @Test(description = "GET /vApp/{id}/networkConfigSection", dependsOnMethods = { "testGetVApp" })
+   @Test(groups = { "live", "user" }, description = "GET /vApp/{id}/networkConfigSection", dependsOnMethods = { "testGetVApp" })
    public void testGetNetworkConfigSection() {
       // The method under test
       NetworkConfigSection section = vAppApi.getNetworkConfigSection(vAppUrn);
@@ -642,7 +586,7 @@
                .ipRanges(newIpRanges).build();
    }
 
-   @Test(description = "GET /vApp/{id}/networkSection", dependsOnMethods = { "testGetVApp" })
+   @Test(groups = { "live", "user" }, description = "GET /vApp/{id}/networkSection", dependsOnMethods = { "testGetVApp" })
    public void testGetNetworkSection() {
       // The method under test
       NetworkSection section = vAppApi.getNetworkSection(vAppUrn);
@@ -651,7 +595,7 @@
       checkNetworkSection(section);
    }
 
-   @Test(description = "GET /vApp/{id}/owner", dependsOnMethods = { "testGetVApp" })
+   @Test(groups = { "live", "user" }, description = "GET /vApp/{id}/owner", dependsOnMethods = { "testGetVApp" })
    public void testGetOwner() {
       // The method under test
       Owner owner = vAppApi.getOwner(vAppUrn);
@@ -660,7 +604,7 @@
       checkOwner(owner);
    }
 
-   @Test(description = "PUT /vApp/{id}/owner", dependsOnMethods = { "testGetOwner" })
+   @Test(groups = { "live", "user" }, description = "PUT /vApp/{id}/owner", dependsOnMethods = { "testGetOwner" })
    public void testEditOwner() {
       Owner newOwner = Owner.builder().user(Reference.builder().href(user.getHref()).type(ADMIN_USER).build()).build();
 
@@ -677,7 +621,7 @@
       assertEquals(modified.getUser().getHref(), newOwner.getUser().getHref());
    }
 
-   @Test(description = "GET /vApp/{id}/productSections", dependsOnMethods = { "testGetVApp" })
+   @Test(groups = { "live", "user" }, description = "GET /vApp/{id}/productSections", dependsOnMethods = { "testGetVApp" })
    public void testGetProductSections() {
       // The method under test
       ProductSectionList sectionList = vAppApi.getProductSections(vAppUrn);
@@ -686,7 +630,7 @@
       checkProductSectionList(sectionList);
    }
 
-   @Test(description = "PUT /vApp/{id}/productSections", dependsOnMethods = { "testGetProductSections" })
+   @Test(groups = { "live", "user" }, description = "PUT /vApp/{id}/productSections", dependsOnMethods = { "testGetProductSections" })
    public void testEditProductSections() {
       // Copy existing section and edit fields
       ProductSectionList oldSections = vAppApi.getProductSections(vAppUrn);
@@ -718,7 +662,7 @@
       assertEquals(modified, newSections);
    }
 
-   @Test(description = "GET /vApp/{id}/startupSection", dependsOnMethods = { "testGetVApp" })
+   @Test(groups = { "live", "user" }, description = "GET /vApp/{id}/startupSection", dependsOnMethods = { "testGetVApp" })
    public void testGetStartupSection() {
       // The method under test
       StartupSection section = vAppApi.getStartupSection(vAppUrn);
@@ -727,7 +671,7 @@
       checkStartupSection(section);
    }
 
-   @Test(description = "PUT /vApp/{id}/startupSection", dependsOnMethods = { "testGetStartupSection" })
+   @Test(groups = { "live", "user" }, description = "PUT /vApp/{id}/startupSection", dependsOnMethods = { "testGetStartupSection" })
    public void testEditStartupSection() {
       // Copy existing section and edit fields
       StartupSection oldSection = vAppApi.getStartupSection(vAppUrn);
@@ -747,26 +691,24 @@
       assertEquals(modified, newSection);
    }
 
-   @Test(description = "PUT /vApp/{id}/metadata", dependsOnMethods = { "testGetVApp" })
+   @Test(groups = { "live", "user" }, description = "PUT /vApp/{id}/metadata", dependsOnMethods = { "testGetVApp" })
    public void testSetMetadataValue() {
       key = name("key-");
       String value = name("value-");
-      metadataValue = MetadataValue.builder().value(value).build();
-      vAppApi.getMetadataApi(vAppUrn).putEntry(key, metadataValue);
+      vAppApi.getMetadataApi(vAppUrn).put(key, value);
 
       // Retrieve the value, and assert it was set correctly
-      MetadataValue newMetadataValue = vAppApi.getMetadataApi(vAppUrn).getValue(key);
+      String newMetadataValue = vAppApi.getMetadataApi(vAppUrn).get(key);
 
       // Check the retrieved object is well formed
-      checkMetadataValueFor(VAPP, newMetadataValue, value);
+      assertEquals(newMetadataValue, value);
    }
 
-   @Test(description = "GET /vApp/{id}/metadata", dependsOnMethods = { "testSetMetadataValue" })
+   @Test(groups = { "live", "user" }, description = "GET /vApp/{id}/metadata", dependsOnMethods = { "testSetMetadataValue" })
    public void testGetMetadata() {
       key = name("key-");
       String value = name("value-");
-      metadataValue = MetadataValue.builder().value(value).build();
-      vAppApi.getMetadataApi(vAppUrn).putEntry(key, metadataValue);
+      vAppApi.getMetadataApi(vAppUrn).put(key, value);
 
       // Call the method being tested
       Metadata metadata = vAppApi.getMetadataApi(vAppUrn).get();
@@ -778,28 +720,23 @@
                String.format(NOT_EMPTY_OBJECT_FMT, "MetadataEntry", "vApp"));
    }
 
-   @Test(description = "GET /vApp/{id}/metadata/{key}", dependsOnMethods = { "testGetMetadata" })
+   @Test(groups = { "live", "user" }, description = "GET /vApp/{id}/metadata/{key}", dependsOnMethods = { "testGetMetadata" })
    public void testGetOrgMetadataValue() {
       
       key = name("key-");
       String value = name("value-");
-      metadataValue = MetadataValue.builder().value(value).build();
-      vAppApi.getMetadataApi(vAppUrn).putEntry(key, metadataValue);
+      vAppApi.getMetadataApi(vAppUrn).put(key, value);
       
       // Call the method being tested
-      MetadataValue newValue = vAppApi.getMetadataApi(vAppUrn).getValue(key);
+      String newValue = vAppApi.getMetadataApi(vAppUrn).get(key);
 
-      String expected = metadataValue.getValue();
-
-      checkMetadataValue(newValue);
-      assertEquals(newValue.getValue(), expected,
-               String.format(CORRECT_VALUE_OBJECT_FMT, "Value", "MetadataValue", expected, newValue.getValue()));
+      assertEquals(newValue, value, String.format(CORRECT_VALUE_OBJECT_FMT, "Value", "MetadataValue", value, newValue));
    }
 
-   @Test(description = "DELETE /vApp/{id}/metadata/{key}", dependsOnMethods = { "testSetMetadataValue" })
+   @Test(groups = { "live", "user" }, description = "DELETE /vApp/{id}/metadata/{key}", dependsOnMethods = { "testSetMetadataValue" })
    public void testRemoveMetadataEntry() {
       // Delete the entry
-      Task task = vAppApi.getMetadataApi(vAppUrn).removeEntry(key);
+      Task task = vAppApi.getMetadataApi(vAppUrn).remove(key);
       retryTaskSuccess.apply(task);
 
       // Confirm the entry has been removed
@@ -809,7 +746,7 @@
       checkMetadataKeyAbsentFor(VAPP, newMetadata, key);
    }
 
-   @Test(description = "POST /vApp/{id}/metadata", dependsOnMethods = { "testGetMetadata" })
+   @Test(groups = { "live", "user" }, description = "POST /vApp/{id}/metadata", dependsOnMethods = { "testGetMetadata" })
    public void testMergeMetadata() {
       Metadata oldMetadata = vAppApi.getMetadataApi(vAppUrn).get();
       Map<String, String> oldMetadataMap = Checks.metadataToMap(oldMetadata);
@@ -817,8 +754,7 @@
       // Store a value, to be removed
       String key = name("key-");
       String value = name("value-");
-      Metadata addedMetadata = Metadata.builder().entry(MetadataEntry.builder().key(key).value(value).build()).build();
-      Task task = vAppApi.getMetadataApi(vAppUrn).merge(addedMetadata);
+      Task task = vAppApi.getMetadataApi(vAppUrn).putAll(ImmutableMap.of(key, value));
       retryTaskSuccess.apply(task);
 
       // Confirm the entry contains everything that was there, and everything that was being added
@@ -833,7 +769,7 @@
    /**
     * @see VAppApi#remove(URI)
     */
-   @Test(description = "DELETE /vApp/{id}")
+   @Test(groups = { "live", "user" }, description = "DELETE /vApp/{id}")
    public void testRemoveVApp() {
       // Create a temporary VApp to remove
       VApp temp = instantiateVApp();
diff --git a/labs/vcloud-director/src/test/java/org/jclouds/vcloud/director/v1_5/features/VAppNetworksLiveTest.java b/labs/vcloud-director/src/test/java/org/jclouds/vcloud/director/v1_5/features/VAppNetworksLiveTest.java
index 4e2656e..7edb518 100644
--- a/labs/vcloud-director/src/test/java/org/jclouds/vcloud/director/v1_5/features/VAppNetworksLiveTest.java
+++ b/labs/vcloud-director/src/test/java/org/jclouds/vcloud/director/v1_5/features/VAppNetworksLiveTest.java
@@ -78,7 +78,7 @@
    protected void tidyUp() {
       if (key != null) {
          try {
-	         Task remove = vAppTemplateApi.getMetadataApi(vAppTemplateUrn).removeEntry(key);
+	         Task remove = vAppTemplateApi.getMetadataApi(vAppTemplateUrn).remove(key);
 	         taskDoneEventually(remove);
          } catch (Exception e) {
             logger.warn(e, "Error when deleting metadata entry '%s'", key);
@@ -189,29 +189,6 @@
              .build();
    }
 
-   private void attachVmToVAppNetwork(Vm vm, String vAppNetworkName) {
-      Set<NetworkConnection> networkConnections = vmApi.getNetworkConnectionSection(vm.getId())
-               .getNetworkConnections();
-
-      NetworkConnectionSection section = NetworkConnectionSection.builder()
-               .info("info")
-               .primaryNetworkConnectionIndex(0)
-               .build();
-      
-      for (NetworkConnection networkConnection : networkConnections) {
-         NetworkConnection newNetworkConnection = networkConnection.toBuilder()
-                  .network(vAppNetworkName)
-                  .isConnected(true)
-                  .networkConnectionIndex(0)
-                  .ipAddressAllocationMode(IpAddressAllocationMode.POOL)
-                  .build();
-         
-         section = section.toBuilder().networkConnection(newNetworkConnection).build();
-      }
-      Task configureNetwork = vmApi.editNetworkConnectionSection(vm.getId(), section);
-      assertTaskSucceedsLong(configureNetwork);
-   }
-
    private IpScope addNewIpScope() {
       IpRange newIpRange = addIpRange();
       IpRanges newIpRanges = IpRanges.builder()
diff --git a/labs/vcloud-director/src/test/java/org/jclouds/vcloud/director/v1_5/features/VAppTemplateApiExpectTest.java b/labs/vcloud-director/src/test/java/org/jclouds/vcloud/director/v1_5/features/VAppTemplateApiExpectTest.java
index 7bf687b..42308aa 100644
--- a/labs/vcloud-director/src/test/java/org/jclouds/vcloud/director/v1_5/features/VAppTemplateApiExpectTest.java
+++ b/labs/vcloud-director/src/test/java/org/jclouds/vcloud/director/v1_5/features/VAppTemplateApiExpectTest.java
@@ -42,7 +42,6 @@
 import org.jclouds.vcloud.director.v1_5.domain.Link;
 import org.jclouds.vcloud.director.v1_5.domain.Metadata;
 import org.jclouds.vcloud.director.v1_5.domain.MetadataEntry;
-import org.jclouds.vcloud.director.v1_5.domain.MetadataValue;
 import org.jclouds.vcloud.director.v1_5.domain.Owner;
 import org.jclouds.vcloud.director.v1_5.domain.Reference;
 import org.jclouds.vcloud.director.v1_5.domain.Task;
@@ -251,7 +250,7 @@
 
       assertEquals(metadata, exampleMetadata());
 
-      Task task = api.getMetadataApi(uri).merge(exampleMetadata());
+      Task task = api.getMetadataApi(uri).putAll(exampleMetadata());
       assertNotNull(task);
    }
 
@@ -276,7 +275,7 @@
             new VcloudHttpRequestPrimer().apiCommand("POST", templateId + "/metadata").xmlFilePayload("/vapptemplate/metadata.xml", METADATA).acceptMedia(TASK).httpRequestBuilder().build(),
             new VcloudHttpResponsePrimer().xmlFilePayload("/vapptemplate/error400.xml", ERROR).httpResponseBuilder().statusCode(400).build()).getVAppTemplateApi();
 
-      api.getMetadataApi(uri).merge(exampleMetadata());
+      api.getMetadataApi(uri).putAll(exampleMetadata());
    }
    
    public void testVappTemplateMetadataValue() {
@@ -293,14 +292,14 @@
       ).getVAppTemplateApi();
 
       assertNotNull(api);
-      MetadataValue metadata = api.getMetadataApi(uri).getValue("12345");
+      String metadata = api.getMetadataApi(uri).get("12345");
 
-      assertEquals(metadata, exampleMetadataValue());
+      assertEquals(metadata, "some value");
 
-      Task task = api.getMetadataApi(uri).putEntry("12345", exampleMetadataValue());
+      Task task = api.getMetadataApi(uri).put("12345", "some value");
       assertNotNull(task);
 
-      task = api.getMetadataApi(uri).removeEntry("12345");
+      task = api.getMetadataApi(uri).remove("12345");
       assertNotNull(task);
    }
 
@@ -312,7 +311,7 @@
             new VcloudHttpRequestPrimer().apiCommand("GET", templateId + "/metadata/12345").acceptMedia(METADATA_ENTRY).httpRequestBuilder().build(),
             new VcloudHttpResponsePrimer().xmlFilePayload("/vapptemplate/error403.xml", ERROR).httpResponseBuilder().statusCode(403).build()).getVAppTemplateApi();
 
-      assertNull(api.getMetadataApi(uri).getValue("12345"));
+      assertNull(api.getMetadataApi(uri).get("12345"));
    }
    
    @Test(expectedExceptions = VCloudDirectorException.class)
@@ -324,7 +323,7 @@
             new VcloudHttpRequestPrimer().apiCommand("PUT", templateId + "/metadata/12345").xmlFilePayload("/vapptemplate/metadataValue.xml", METADATA_ENTRY).acceptMedia(TASK).httpRequestBuilder().build(),
             new VcloudHttpResponsePrimer().xmlFilePayload("/vapptemplate/error400.xml", ERROR).httpResponseBuilder().statusCode(400).build()).getVAppTemplateApi();
 
-      api.getMetadataApi(uri).putEntry("12345", exampleMetadataValue());
+      api.getMetadataApi(uri).put("12345", "some value");
    }
 
    @Test(expectedExceptions = ResourceNotFoundException.class)
@@ -336,7 +335,7 @@
             new VcloudHttpRequestPrimer().apiCommand("DELETE", templateId + "/metadata/12345").acceptMedia(TASK).httpRequestBuilder().build(),
             new VcloudHttpResponsePrimer().xmlFilePayload("/vapptemplate/error403.xml", ERROR).httpResponseBuilder().statusCode(403).build()).getVAppTemplateApi();
 
-      api.getMetadataApi(uri).removeEntry("12345");
+      api.getMetadataApi(uri).remove("12345");
    }
 
    @Test(expectedExceptions = VCloudDirectorException.class)
@@ -437,8 +436,4 @@
             .entry(MetadataEntry.builder().key("key").value("value").build()).build();
    }
 
-   private MetadataValue exampleMetadataValue() {
-      return MetadataValue.builder().value("some value").build();
-   }
-
 }
diff --git a/labs/vcloud-director/src/test/java/org/jclouds/vcloud/director/v1_5/features/VAppTemplateApiLiveTest.java b/labs/vcloud-director/src/test/java/org/jclouds/vcloud/director/v1_5/features/VAppTemplateApiLiveTest.java
index 341c38e..7ed8579 100644
--- a/labs/vcloud-director/src/test/java/org/jclouds/vcloud/director/v1_5/features/VAppTemplateApiLiveTest.java
+++ b/labs/vcloud-director/src/test/java/org/jclouds/vcloud/director/v1_5/features/VAppTemplateApiLiveTest.java
@@ -23,7 +23,6 @@
 import static org.jclouds.vcloud.director.v1_5.domain.Checks.checkMetadata;
 import static org.jclouds.vcloud.director.v1_5.domain.Checks.checkMetadataFor;
 import static org.jclouds.vcloud.director.v1_5.domain.Checks.checkMetadataKeyAbsentFor;
-import static org.jclouds.vcloud.director.v1_5.domain.Checks.checkMetadataValue;
 import static org.jclouds.vcloud.director.v1_5.domain.Checks.checkNetworkConfigSection;
 import static org.jclouds.vcloud.director.v1_5.domain.Checks.checkOvfEnvelope;
 import static org.jclouds.vcloud.director.v1_5.domain.Checks.checkOvfNetworkSection;
@@ -48,7 +47,6 @@
 import org.jclouds.vcloud.director.v1_5.domain.Link.Rel;
 import org.jclouds.vcloud.director.v1_5.domain.Metadata;
 import org.jclouds.vcloud.director.v1_5.domain.MetadataEntry;
-import org.jclouds.vcloud.director.v1_5.domain.MetadataValue;
 import org.jclouds.vcloud.director.v1_5.domain.Owner;
 import org.jclouds.vcloud.director.v1_5.domain.ProductSectionList;
 import org.jclouds.vcloud.director.v1_5.domain.Reference;
@@ -84,7 +82,7 @@
    protected void tidyUp() {
       if (key != null) {
          try {
-            Task remove = vAppTemplateApi.getMetadataApi(vAppTemplateUrn).removeEntry(key);
+            Task remove = vAppTemplateApi.getMetadataApi(vAppTemplateUrn).remove(key);
             taskDoneEventually(remove);
          } catch (Exception e) {
             logger.warn(e, "Error when deleting metadata entry '%s'", key);
@@ -135,20 +133,6 @@
 
       checkProductSectionList(productSectionList);
    }
-
-   @Test(description = "PUT /vAppTemplate/{id}/productSections")
-   public void testEditProductSections() {
-      // TODO make a real modification
-
-      ProductSectionList origSections = vAppTemplateApi.getProductSections(vApp.getId());
-      ProductSectionList newSections = origSections.toBuilder().build();
-
-      Task task = vAppTemplateApi.editProductSections(vApp.getId(), newSections);
-      assertTaskSucceeds(task);
-
-      ProductSectionList modified = vAppTemplateApi.getProductSections(vApp.getId());
-      checkProductSectionList(modified);
-   }
    
    @Test(description = "GET /vAppTemplate/{id}/leaseSettingsSection")
    public void testGetLeaseSettingsSection() {
@@ -171,10 +155,9 @@
       Metadata metadata = vAppTemplateApi.getMetadataApi(vAppTemplateUrn).get();
       MetadataEntry entry = Iterables.get(metadata.getMetadataEntries(), 0);
 
-      MetadataValue val = vAppTemplateApi.getMetadataApi(vAppTemplateUrn).getValue(entry.getKey());
+      String val = vAppTemplateApi.getMetadataApi(vAppTemplateUrn).get(entry.getKey());
 
-      checkMetadataValue(val);
-      assertEquals(val.getValue(), entry.getValue());
+      assertEquals(val, entry.getValue());
    }
 
    @Test(description = "GET /vAppTemplate/{id}/networkConfigSection")
@@ -219,10 +202,8 @@
 
       key = name("key-");
       val = name("value-");
-      MetadataEntry metadataEntry = MetadataEntry.builder().entry(key, val).build();
-      Metadata metadata = Metadata.builder().fromMetadata(oldMetadata).entry(metadataEntry).build();
 
-      final Task task = vAppTemplateApi.getMetadataApi(vAppTemplateUrn).merge(metadata);
+      final Task task = vAppTemplateApi.getMetadataApi(vAppTemplateUrn).putAll(ImmutableMap.of(key, val));
       assertTaskSucceeds(task);
 
       Metadata newMetadata = vAppTemplateApi.getMetadataApi(vAppTemplateUrn).get();
@@ -234,18 +215,17 @@
    @Test(description = "PUT /vAppTemplate/{id}/metadata/{key}", dependsOnMethods = { "testEditMetadata" })
    public void testEditMetadataValue() {
       val = "new" + val;
-      MetadataValue metadataValue = MetadataValue.builder().value(val).build();
 
-      final Task task = vAppTemplateApi.getMetadataApi(vAppTemplateUrn).putEntry(key, metadataValue);
+      final Task task = vAppTemplateApi.getMetadataApi(vAppTemplateUrn).put(key, val);
       retryTaskSuccess.apply(task);
 
-      MetadataValue newMetadataValue = vAppTemplateApi.getMetadataApi(vAppTemplateUrn).getValue(key);
-      assertEquals(newMetadataValue.getValue(), metadataValue.getValue());
+      String newMetadataValue = vAppTemplateApi.getMetadataApi(vAppTemplateUrn).get(key);
+      assertEquals(newMetadataValue, val);
    }
 
    @Test(description = "DELETE /vAppTemplate/{id}/metadata/{key}", dependsOnMethods = { "testGetMetadataValue" })
    public void testRemoveVAppTemplateMetadataValue() {
-      final Task deletionTask = vAppTemplateApi.getMetadataApi(vAppTemplateUrn).removeEntry(key);
+      final Task deletionTask = vAppTemplateApi.getMetadataApi(vAppTemplateUrn).remove(key);
       assertTaskSucceeds(deletionTask);
 
       Metadata newMetadata = vAppTemplateApi.getMetadataApi(vAppTemplateUrn).get();
@@ -274,15 +254,15 @@
       VAppTemplate clonedVappTemplate = cloneVAppTemplate(true);
 
       // Confirm that "get" works pre-remove
-      VAppTemplate vAppTemplatePreDelete = vAppTemplateApi.get(clonedVappTemplate.getId());
+      VAppTemplate vAppTemplatePreDelete = vAppTemplateApi.get(clonedVappTemplate.getHref());
       checkVAppTemplate(vAppTemplatePreDelete);
 
       // Delete the template
-      final Task task = vAppTemplateApi.remove(clonedVappTemplate.getId());
+      final Task task = vAppTemplateApi.remove(clonedVappTemplate.getHref());
       assertTaskSucceeds(task);
 
       // Confirm that can't access post-remove, i.e. template has been removed
-      VAppTemplate removed = vAppTemplateApi.get(clonedVappTemplate.getId());
+      VAppTemplate removed = vAppTemplateApi.get(clonedVappTemplate.getHref());
       assertNull(removed);
    }
 
@@ -305,7 +285,7 @@
       // First disable so that enable really has some work to do...
       vAppTemplateApi.disableDownload(vAppTemplateUrn);
       final Task task = vAppTemplateApi.enableDownload(vAppTemplateUrn);
-      assertTaskSucceeds(task);
+      assertTaskSucceedsLong(task);
 
       // TODO Check that it really is enabled. The only thing I can see for determining this
       // is the undocumented "download" link in the VAppTemplate. But that is brittle and we
diff --git a/labs/vcloud-director/src/test/java/org/jclouds/vcloud/director/v1_5/features/VdcApiExpectTest.java b/labs/vcloud-director/src/test/java/org/jclouds/vcloud/director/v1_5/features/VdcApiExpectTest.java
index c5d02f6..7342a44 100644
--- a/labs/vcloud-director/src/test/java/org/jclouds/vcloud/director/v1_5/features/VdcApiExpectTest.java
+++ b/labs/vcloud-director/src/test/java/org/jclouds/vcloud/director/v1_5/features/VdcApiExpectTest.java
@@ -35,7 +35,6 @@
 import org.jclouds.vcloud.director.v1_5.domain.Media;
 import org.jclouds.vcloud.director.v1_5.domain.Media.ImageType;
 import org.jclouds.vcloud.director.v1_5.domain.Metadata;
-import org.jclouds.vcloud.director.v1_5.domain.MetadataValue;
 import org.jclouds.vcloud.director.v1_5.domain.Owner;
 import org.jclouds.vcloud.director.v1_5.domain.Reference;
 import org.jclouds.vcloud.director.v1_5.domain.User;
@@ -371,9 +370,7 @@
                .xmlFilePayload("/vdc/metadataValue.xml", VCloudDirectorMediaType.METADATA_VALUE)
                .httpResponseBuilder().build());
       
-      MetadataValue expected = metadataValue();
-     
-      assertEquals(api.getVdcApi().getMetadataApi(vdcUri).getValue("key"), expected);
+      assertEquals(api.getVdcApi().getMetadataApi(vdcUri).get("key"), "");
    }
 
    public static Vdc getVdc() {
@@ -582,9 +579,4 @@
       return null;
    }
    
-   private MetadataValue metadataValue() {
-      // TODO Auto-generated method stub
-      return null;
-   }
-   
 }
diff --git a/labs/vcloud-director/src/test/java/org/jclouds/vcloud/director/v1_5/features/VdcApiLiveTest.java b/labs/vcloud-director/src/test/java/org/jclouds/vcloud/director/v1_5/features/VdcApiLiveTest.java
index a03552a..93e1bed 100644
--- a/labs/vcloud-director/src/test/java/org/jclouds/vcloud/director/v1_5/features/VdcApiLiveTest.java
+++ b/labs/vcloud-director/src/test/java/org/jclouds/vcloud/director/v1_5/features/VdcApiLiveTest.java
@@ -25,14 +25,15 @@
 import static org.testng.Assert.assertEquals;
 import static org.testng.Assert.assertFalse;
 import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertTrue;
 import static org.testng.Assert.fail;
 
 import java.util.Map;
 import java.util.Set;
 
+import org.jclouds.dmtf.ovf.NetworkSection;
 import org.jclouds.vcloud.director.v1_5.domain.Checks;
 import org.jclouds.vcloud.director.v1_5.domain.Metadata;
-import org.jclouds.vcloud.director.v1_5.domain.MetadataValue;
 import org.jclouds.vcloud.director.v1_5.domain.Reference;
 import org.jclouds.vcloud.director.v1_5.domain.ResourceEntity;
 import org.jclouds.vcloud.director.v1_5.domain.Task;
@@ -121,7 +122,7 @@
 
       if (metadataSet) {
          try {
-            Task remove = adminContext.getApi().getVdcApi().getMetadataApi(vdcUrn).removeEntry("key");
+            Task remove = adminContext.getApi().getVdcApi().getMetadataApi(vdcUrn).remove("key");
             taskDoneEventually(remove);
          } catch (Exception e) {
             logger.warn(e, "Error deleting metadata entry");
@@ -139,9 +140,12 @@
 
    @Test(description = "POST /vdc/{id}/action/captureVApp", dependsOnMethods = { "testInstantiateVAppTemplate" })
    public void testCaptureVApp() {
+	  VAppTemplate vAppTemplate = vappTemplateApi.get(vAppTemplateUrn);
       String name = name("captured-");
 
-      CaptureVAppParams captureVappParams = CaptureVAppParams.builder().name(name).source(instantiatedVApp.getHref())
+      CaptureVAppParams captureVappParams = CaptureVAppParams.builder()
+    		  .name(name)
+    		  .source(instantiatedVApp.getHref())
       // TODO: test optional params
       // .description("")
       // .sections(sections) // TODO: ovf sections
@@ -161,15 +165,16 @@
    @Test(description = "POST /vdc/{id}/action/cloneVApp", dependsOnMethods = { "testInstantiateVAppTemplate" })
    public void testCloneVApp() {
       CloneVAppParams cloneVappParams = CloneVAppParams.builder().source(instantiatedVApp.getHref())
-      // TODO: test optional params
-      // .name("")
-      // .description("")
-      // .deploy(true)
-      // .isSourceDelete(true)
-      // .powerOn(true)
-      // .instantiationParams(InstantiationParams.builder()
-      // .sections(sections) // TODO: ovf sections? various tests?
-      // .build())
+    		  .name(name("vappClone-"))
+    		  .deploy(true)
+		      // TODO: test optional params
+		      // .description("")
+		      // .isSourceDelete(true)
+		      // .powerOn(true)
+		      // .instantiationParams(InstantiationParams.builder()
+		      // .sections(sections) 
+    		  // TODO: ovf sections? various tests?
+		      // .build())
 
                // Reserved. Unimplemented params; may test eventually when implemented
                // .vAppParent(vAppParentRef)
@@ -188,7 +193,10 @@
    @Test(description = "POST /vdc/{id}/action/cloneVAppTemplate")
    public void testCloneVAppTemplate() {
       clonedVAppTemplate = vdcApi.cloneVAppTemplate(vdcUrn,
-               CloneVAppTemplateParams.builder().source(lazyGetVAppTemplate().getHref()).build());
+               CloneVAppTemplateParams.builder()
+               	  .name(name("vappTemplateClone-"))
+                  .source(lazyGetVAppTemplate().getHref())
+                  .build());
 
       Task task = Iterables.getFirst(clonedVAppTemplate.getTasks(), null);
       assertNotNull(task, "vdcApi.cloneVAppTemplate returned VAppTemplate that did not contain any tasks");
@@ -299,22 +307,12 @@
 
    }
 
-   private void setupMetadata() {
-      adminContext.getApi().getVdcApi().getMetadataApi(vdcUrn)
-               .putEntry("key", MetadataValue.builder().value("value").build());
-      metadataSet = true;
-   }
-
    @Test(description = "GET /vdc/{id}/metadata", dependsOnMethods = { "testGetVdc" })
    public void testGetMetadata() {
-      if (adminContext != null) {
-         setupMetadata();
-      }
-
       Metadata metadata = vdcApi.getMetadataApi(vdcUrn).get();
 
       // required for testing
-      assertFalse(Iterables.isEmpty(metadata.getMetadataEntries()),
+      assertTrue(Iterables.isEmpty(metadata.getMetadataEntries()),
                String.format(OBJ_FIELD_REQ_LIVE, VDC, "metadata.entries"));
 
       Checks.checkMetadataFor(VDC, metadata);
@@ -322,14 +320,16 @@
 
    @Test(description = "GET /vdc/{id}/metadata/{key}", dependsOnMethods = { "testGetMetadata" })
    public void testGetMetadataValue() {
+      // setupMetadata();
       // First find a key
       Metadata metadata = vdcApi.getMetadataApi(vdcUrn).get();
       Map<String, String> metadataMap = Checks.metadataToMap(metadata);
       String key = Iterables.getFirst(metadataMap.keySet(), "MadeUpKey!");
       String value = metadataMap.get(key);
 
-      MetadataValue metadataValue = vdcApi.getMetadataApi(vdcUrn).getValue(key);
+      String metadataValue = vdcApi.getMetadataApi(vdcUrn).get(key);
 
-      Checks.checkMetadataValueFor(VDC, metadataValue, value);
+      assertEquals(metadataValue, value);
    }
+   
 }
diff --git a/labs/vcloud-director/src/test/java/org/jclouds/vcloud/director/v1_5/features/VmApiLiveTest.java b/labs/vcloud-director/src/test/java/org/jclouds/vcloud/director/v1_5/features/VmApiLiveTest.java
index a2bfbce..e661a73 100644
--- a/labs/vcloud-director/src/test/java/org/jclouds/vcloud/director/v1_5/features/VmApiLiveTest.java
+++ b/labs/vcloud-director/src/test/java/org/jclouds/vcloud/director/v1_5/features/VmApiLiveTest.java
@@ -20,7 +20,6 @@
 
 import static org.jclouds.vcloud.director.v1_5.VCloudDirectorLiveTestConstants.CORRECT_VALUE_OBJECT_FMT;
 import static org.jclouds.vcloud.director.v1_5.VCloudDirectorLiveTestConstants.ENTITY_EQUAL;
-import static org.jclouds.vcloud.director.v1_5.VCloudDirectorLiveTestConstants.NOT_EMPTY_OBJECT_FMT;
 import static org.jclouds.vcloud.director.v1_5.VCloudDirectorLiveTestConstants.OBJ_FIELD_EQ;
 import static org.jclouds.vcloud.director.v1_5.VCloudDirectorLiveTestConstants.TASK_COMPLETE_TIMELY;
 import static org.jclouds.vcloud.director.v1_5.VCloudDirectorMediaType.MEDIA;
@@ -28,8 +27,6 @@
 import static org.jclouds.vcloud.director.v1_5.domain.Checks.checkMetadata;
 import static org.jclouds.vcloud.director.v1_5.domain.Checks.checkMetadataFor;
 import static org.jclouds.vcloud.director.v1_5.domain.Checks.checkMetadataKeyAbsentFor;
-import static org.jclouds.vcloud.director.v1_5.domain.Checks.checkMetadataValue;
-import static org.jclouds.vcloud.director.v1_5.domain.Checks.checkMetadataValueFor;
 import static org.jclouds.vcloud.director.v1_5.domain.Checks.checkNetworkConnectionSection;
 import static org.jclouds.vcloud.director.v1_5.domain.Checks.checkOperatingSystemSection;
 import static org.jclouds.vcloud.director.v1_5.domain.Checks.checkProductSectionList;
@@ -59,8 +56,6 @@
 import org.jclouds.vcloud.director.v1_5.AbstractVAppApiLiveTest;
 import org.jclouds.vcloud.director.v1_5.domain.Checks;
 import org.jclouds.vcloud.director.v1_5.domain.Metadata;
-import org.jclouds.vcloud.director.v1_5.domain.MetadataEntry;
-import org.jclouds.vcloud.director.v1_5.domain.MetadataValue;
 import org.jclouds.vcloud.director.v1_5.domain.ProductSectionList;
 import org.jclouds.vcloud.director.v1_5.domain.RasdItemsList;
 import org.jclouds.vcloud.director.v1_5.domain.Reference;
@@ -73,14 +68,13 @@
 import org.jclouds.vcloud.director.v1_5.domain.VmQuestionAnswer;
 import org.jclouds.vcloud.director.v1_5.domain.VmQuestionAnswerChoice;
 import org.jclouds.vcloud.director.v1_5.domain.dmtf.RasdItem;
+import org.jclouds.vcloud.director.v1_5.domain.network.NetworkConfiguration;
 import org.jclouds.vcloud.director.v1_5.domain.network.NetworkConnection;
+import org.jclouds.vcloud.director.v1_5.domain.network.Network.FenceMode;
 import org.jclouds.vcloud.director.v1_5.domain.network.NetworkConnection.IpAddressAllocationMode;
 import org.jclouds.vcloud.director.v1_5.domain.params.DeployVAppParams;
 import org.jclouds.vcloud.director.v1_5.domain.params.MediaInsertOrEjectParams;
-import org.jclouds.vcloud.director.v1_5.domain.params.RelocateParams;
 import org.jclouds.vcloud.director.v1_5.domain.params.UndeployVAppParams;
-import org.jclouds.vcloud.director.v1_5.domain.query.QueryResultRecordType;
-import org.jclouds.vcloud.director.v1_5.domain.query.QueryResultRecords;
 import org.jclouds.vcloud.director.v1_5.domain.section.GuestCustomizationSection;
 import org.jclouds.vcloud.director.v1_5.domain.section.NetworkConnectionSection;
 import org.jclouds.vcloud.director.v1_5.domain.section.OperatingSystemSection;
@@ -92,7 +86,9 @@
 
 import com.google.common.base.Function;
 import com.google.common.base.Predicate;
+import com.google.common.base.Predicates;
 import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.Iterables;
 import com.google.common.collect.Sets;
 
@@ -104,7 +100,7 @@
 @Test(groups = { "live", "user" }, singleThreaded = true, testName = "VmApiLiveTest")
 public class VmApiLiveTest extends AbstractVAppApiLiveTest {
 
-   private MetadataValue metadataValue;
+   private String metadataValue;
    private String key;
    private boolean testUserCreated = false;
 
@@ -119,14 +115,6 @@
 
    @AfterClass(alwaysRun = true, dependsOnMethods = { "cleanUpEnvironment" })
    public void cleanUp() {
-      if (adminContext != null && mediaUrn != null) {
-         try {
-            Task remove = context.getApi().getMediaApi().remove(mediaUrn);
-            taskDoneEventually(remove);
-         } catch (Exception e) {
-            logger.warn("Error when deleting media: %s", e.getMessage());
-         }
-      }
       if (adminContext != null && testUserCreated && userUrn != null) {
          try {
             adminContext.getApi().getUserApi().remove(userUrn);
@@ -150,6 +138,8 @@
       // Check the required fields are set
       assertEquals(vm.isDeployed(), Boolean.FALSE,
                String.format(OBJ_FIELD_EQ, VM, "deployed", "FALSE", vm.isDeployed().toString()));
+      String vAppNetworkName = context.getApi().getNetworkApi().get(networkUrn).getName();
+      attachVmToVAppNetwork(vm, vAppNetworkName);
 
       // Check status
       assertVmStatus(vmUrn, Status.POWERED_OFF);
@@ -219,7 +209,7 @@
 
       // The method under test
       Task reboot = vmApi.reboot(vmUrn);
-      assertTaskSucceedsLong(reboot);
+       assertTaskSucceedsLong(reboot);
 
       // Get the edited Vm
       vm = vmApi.get(vmUrn);
@@ -232,7 +222,7 @@
    public void testShutdown() {
       // Power on Vm
       vm = powerOnVm(vmUrn);
-
+      
       // The method under test
       Task shutdown = vmApi.shutdown(vmUrn);
       assertTaskSucceedsLong(shutdown);
@@ -302,7 +292,7 @@
    public void testPowerOffVm() {
       // Power on Vm
       vm = powerOnVm(vmUrn);
-
+      
       // The method under test
       // NB this will put the vm in partially powered off state
       Task powerOffVm = vmApi.powerOff(vmUrn);
@@ -315,16 +305,6 @@
       assertVmStatus(vmUrn, Status.POWERED_OFF);
    }
 
-   @Test(description = "POST /vApp/{id}/action/consolidate", dependsOnMethods = { "testDeployVm" })
-   public void testConsolidateVm() {
-      // Power on Vm
-      vm = powerOnVm(vmUrn);
-
-      // The method under test
-      Task consolidateVm = vmApi.consolidate(vmUrn);
-      assertTrue(retryTaskSuccess.apply(consolidateVm), String.format(TASK_COMPLETE_TIMELY, "consolidateVm"));
-   }
-
    @Test(description = "POST /vApp/{id}/action/discardSuspendedState", dependsOnMethods = { "testDeployVm" })
    public void testDiscardSuspendedState() {
       // Suspend the Vm
@@ -346,20 +326,6 @@
       assertTrue(retryTaskSuccess.apply(installVMwareTools), String.format(TASK_COMPLETE_TIMELY, "installVMwareTools"));
    }
 
-   // NOTE This test is disabled, as it is not possible to look up datastores using the User API
-   @Test(description = "POST /vApp/{id}/action/relocate", dependsOnMethods = { "testGetVm" })
-   public void testRelocate() {
-      // Relocate to the last of the available datastores
-      QueryResultRecords records = context.getApi().getQueryApi().queryAll("datastore");
-      QueryResultRecordType datastore = Iterables.getLast(records.getRecords());
-      RelocateParams params = RelocateParams.builder().datastore(Reference.builder().href(datastore.getHref()).build())
-               .build();
-
-      // The method under test
-      Task relocate = vmApi.relocate(vmUrn, params);
-      assertTrue(retryTaskSuccess.apply(relocate), String.format(TASK_COMPLETE_TIMELY, "relocate"));
-   }
-
    @Test(description = "POST /vApp/{id}/action/upgradeHardwareVersion", dependsOnMethods = { "testGetVm" })
    public void testUpgradeHardwareVersion() {
       // Power off Vm
@@ -414,24 +380,27 @@
       assertEquals(modified, newSection, String.format(ENTITY_EQUAL, "GuestCustomizationSection"));
    }
 
-   // FIXME
-   // "Error: The requested operation on media "com.vmware.vcloud.entity.media:abfcb4b7-809f-4b50-a0aa-8c97bf09a5b0" is not supported in the current state."
-   @Test(description = "PUT /vApp/{id}/media/action/insertMedia", dependsOnMethods = { "testGetVm" })
-   public void testInsertMedia() {
-      // Setup media params from configured media id
-      MediaInsertOrEjectParams params = MediaInsertOrEjectParams.builder()
-               .media(Reference.builder().href(lazyGetMedia().getHref()).type(MEDIA).build()).build();
+	@Test(description = "PUT /vApp/{id}/media/action/insertMedia", dependsOnMethods = { "testGetVm" })
+	public void testInsertMedia() {
+		// Setup media params from configured media id
+		MediaInsertOrEjectParams params = MediaInsertOrEjectParams
+				.builder()
+				.media(Reference.builder().href(lazyGetMedia().getHref())
+						.type(MEDIA).build()).build();
 
-      // The method under test
-      Task insertMedia = vmApi.insertMedia(vmUrn, params);
-      assertTrue(retryTaskSuccess.apply(insertMedia), String.format(TASK_COMPLETE_TIMELY, "insertMedia"));
-   }
+		// The method under test
+		Task insertMediaTask = vmApi.insertMedia(vmUrn, params);
+		assertTrue(retryTaskSuccess.apply(insertMediaTask),
+				String.format(TASK_COMPLETE_TIMELY, "insertMedia"));
+	}
 
    @Test(description = "PUT /vApp/{id}/media/action/ejectMedia", dependsOnMethods = { "testInsertMedia" })
    public void testEjectMedia() {
+	   
       // Setup media params from configured media id
       MediaInsertOrEjectParams params = MediaInsertOrEjectParams.builder()
-               .media(Reference.builder().href(lazyGetMedia().getHref()).type(MEDIA).build()).build();
+               .media(Reference.builder()
+            		   .href(lazyGetMedia().getHref()).type(MEDIA).build()).build();
 
       // The method under test
       Task ejectMedia = vmApi.ejectMedia(vmUrn, params);
@@ -448,39 +417,47 @@
       });
    }
 
-   // FIXME "Task error: Unable to perform this action. Contact your cloud administrator."
    @Test(description = "PUT /vApp/{id}/networkConnectionSection", dependsOnMethods = { "testEditGuestCustomizationSection" })
-   public void testEditNetworkConnectionSection() {
-      powerOffVm(vmUrn);
-      // Look up a network in the Vdc
-      Set<Reference> networks = vdc.getAvailableNetworks();
-      Reference network = Iterables.getLast(networks);
+	public void testEditNetworkConnectionSection() {
 
-      // Copy existing section and edit fields
-      NetworkConnectionSection oldSection = vmApi.getNetworkConnectionSection(vmUrn);
-      NetworkConnectionSection newSection = oldSection
-               .toBuilder()
-               .networkConnection(
-                        NetworkConnection.builder().ipAddressAllocationMode(IpAddressAllocationMode.DHCP.toString())
-                                 .network(network.getName()).build()).build();
+		// Look up a network in the Vdc
+		Set<Reference> networks = vdc.getAvailableNetworks();
+		Reference network = Iterables.getLast(networks);
 
-      // The method under test
-      Task editNetworkConnectionSection = vmApi.editNetworkConnectionSection(vmUrn, newSection);
-      assertTrue(retryTaskSuccess.apply(editNetworkConnectionSection),
-               String.format(TASK_COMPLETE_TIMELY, "editNetworkConnectionSection"));
+		// Copy existing section and edit fields
+		NetworkConnectionSection oldSection = vmApi
+				.getNetworkConnectionSection(vmUrn);
+		NetworkConnection newNetworkConnection = NetworkConnection.builder()
+				.network(network.getName()).networkConnectionIndex(1)
+				.ipAddressAllocationMode(IpAddressAllocationMode.DHCP).build();
+		NetworkConnectionSection newSection = oldSection.toBuilder()
+				.networkConnection(newNetworkConnection).build();
 
-      // Retrieve the modified section
-      NetworkConnectionSection modified = vmApi.getNetworkConnectionSection(vmUrn);
+		// The method under test
+		Task editNetworkConnectionSection = vmApi.editNetworkConnectionSection(
+				vmUrn, newSection);
+		assertTrue(retryTaskSuccess.apply(editNetworkConnectionSection),
+				String.format(TASK_COMPLETE_TIMELY,
+						"editNetworkConnectionSection"));
 
-      // Check the retrieved object is well formed
-      checkNetworkConnectionSection(modified);
+		// Retrieve the modified section
+		NetworkConnectionSection modified = vmApi
+				.getNetworkConnectionSection(vmUrn);
 
-      // Check the modified section has an extra network connection
-      assertEquals(modified.getNetworkConnections().size(), newSection.getNetworkConnections().size() + 1);
+		// Check the retrieved object is well formed
+		checkNetworkConnectionSection(modified);
 
-      // Check the section was modified correctly
-      assertEquals(modified, newSection, String.format(ENTITY_EQUAL, "NetworkConnectionSection"));
-   }
+		// Check the section was modified correctly
+		for (NetworkConnection connection : modified.getNetworkConnections()) {
+			if (connection.getNetwork().equals(
+					newNetworkConnection.getNetwork())) {
+				assertTrue(connection.getIpAddressAllocationMode().equals(
+						newNetworkConnection.getIpAddressAllocationMode()));
+				assertTrue(connection.getNetworkConnectionIndex() == newNetworkConnection
+						.getNetworkConnectionIndex());
+			}
+		}
+	}
 
    @Test(description = "GET /vApp/{id}/operatingSystemSection", dependsOnMethods = { "testGetVm" })
    public void testGetOperatingSystemSection() {
@@ -597,11 +574,10 @@
       checkRuntimeInfoSection(section);
    }
 
-   // FIXME If still failing, consider escalating?
    @Test(description = "GET /vApp/{id}/screen", dependsOnMethods = { "testInstallVMwareTools" })
    public void testGetScreenImage() {
       // Power on Vm
-      vm = powerOnVm(vmUrn);
+      vm = powerOnVm(vmUrn); // we need to have a way to wait for complete bootstrap
 
       // The method under test
       byte[] image = vmApi.getScreenImage(vmUrn);
@@ -872,50 +848,53 @@
    @Test(description = "PUT /vApp/{id}/metadata/{key}", dependsOnMethods = { "testGetVm" })
    public void testSetMetadataValue() {
       key = name("key-");
-      String value = name("value-");
-      metadataValue = MetadataValue.builder().value(value).build();
-      vmApi.getMetadataApi(vmUrn).putEntry(key, metadataValue);
+      metadataValue = name("value-");
+      //TODO: block!!
+      vmApi.getMetadataApi(vmUrn).put(key, metadataValue);
 
       // Retrieve the value, and assert it was set correctly
-      MetadataValue newMetadataValue = vmApi.getMetadataApi(vmUrn).getValue(key);
+      String newMetadataValue = vmApi.getMetadataApi(vmUrn).get(key);
 
       // Check the retrieved object is well formed
-      checkMetadataValueFor(VM, newMetadataValue, value);
+      assertEquals(newMetadataValue, metadataValue,
+            String.format(CORRECT_VALUE_OBJECT_FMT, "Value", "MetadataValue", metadataValue, newMetadataValue));
    }
 
-   @Test(description = "GET /vApp/{id}/metadata", dependsOnMethods = { "testSetMetadataValue" })
-   public void testGetMetadata() {
-      // Call the method being tested
-      Metadata metadata = vmApi.getMetadataApi(vmUrn).get();
+	@Test(description = "GET /vApp/{id}/metadata", dependsOnMethods = { "testSetMetadataValue" })
+	public void testGetMetadata() {
 
-      checkMetadata(metadata);
+		key = name("key-");
+		metadataValue = name("value-");
 
-      // Check requirements for this test
-      assertTrue(Iterables.isEmpty(metadata.getMetadataEntries()),
-               String.format(NOT_EMPTY_OBJECT_FMT, "MetadataEntry", "vm"));
-   }
+		vmApi.getMetadataApi(vmUrn).put(key, metadataValue);
+		// Call the method being tested
+		Metadata metadata = vmApi.getMetadataApi(vmUrn).get();
+
+		checkMetadata(metadata);
+		
+		// Check requirements for this test
+		assertTrue(metadata.containsValue(metadataValue), String.format(CORRECT_VALUE_OBJECT_FMT, "Value", "MetadataValue", metadata.get(key), metadataValue));
+	}
 
    @Test(description = "GET /vApp/{id}/metadata/{key}", dependsOnMethods = { "testGetMetadata" })
    public void testGetOrgMetadataValue() {
       key = name("key-");
-      String value = name("value-");
-      metadataValue = MetadataValue.builder().value(value).build();
-      vmApi.getMetadataApi(vmUrn).putEntry(key, metadataValue);
+      metadataValue = name("value-");
+
+      //TODO: block!!
+      vmApi.getMetadataApi(vmUrn).put(key, metadataValue);
 
       // Call the method being tested
-      MetadataValue metadataValue = vmApi.getMetadataApi(vmUrn).getValue(key);
-
-      String expected = metadataValue.getValue();
-
-      checkMetadataValue(metadataValue);
-      assertEquals(metadataValue.getValue(), expected,
-               String.format(CORRECT_VALUE_OBJECT_FMT, "Value", "MetadataValue", expected, metadataValue.getValue()));
+      String newMetadataValue = vmApi.getMetadataApi(vmUrn).get(key);
+      
+      assertEquals(newMetadataValue, metadataValue,
+            String.format(CORRECT_VALUE_OBJECT_FMT, "Value", "MetadataValue", metadataValue, newMetadataValue));
    }
 
    @Test(description = "DELETE /vApp/{id}/metadata/{key}", dependsOnMethods = { "testSetMetadataValue" })
    public void testRemoveMetadataEntry() {
       // Delete the entry
-      Task task = vmApi.getMetadataApi(vmUrn).removeEntry(key);
+      Task task = vmApi.getMetadataApi(vmUrn).remove(key);
       retryTaskSuccess.apply(task);
 
       // Confirm the entry has been removed
@@ -933,8 +912,7 @@
       // Store a value, to be removed
       String key = name("key-");
       String value = name("value-");
-      Metadata addedMetadata = Metadata.builder().entry(MetadataEntry.builder().key(key).value(value).build()).build();
-      Task task = vmApi.getMetadataApi(vmUrn).merge(addedMetadata);
+      Task task = vmApi.getMetadataApi(vmUrn).putAll(ImmutableMap.of(key, value));
       retryTaskSuccess.apply(task);
 
       // Confirm the entry contains everything that was there, and everything that was being added
diff --git a/labs/vcloud-director/src/test/java/org/jclouds/vcloud/director/v1_5/features/admin/AdminVdcApiLiveTest.java b/labs/vcloud-director/src/test/java/org/jclouds/vcloud/director/v1_5/features/admin/AdminVdcApiLiveTest.java
index 8e5eeb0..d8ae806 100644
--- a/labs/vcloud-director/src/test/java/org/jclouds/vcloud/director/v1_5/features/admin/AdminVdcApiLiveTest.java
+++ b/labs/vcloud-director/src/test/java/org/jclouds/vcloud/director/v1_5/features/admin/AdminVdcApiLiveTest.java
@@ -21,14 +21,12 @@
 import static org.jclouds.vcloud.director.v1_5.VCloudDirectorLiveTestConstants.OBJ_REQ_LIVE;
 import static org.testng.Assert.assertEquals;
 import static org.testng.Assert.assertNotNull;
-import static org.testng.Assert.fail;
+import static org.testng.Assert.assertNull;
 
 import org.jclouds.vcloud.director.v1_5.VCloudDirectorException;
 import org.jclouds.vcloud.director.v1_5.domain.AdminVdc;
 import org.jclouds.vcloud.director.v1_5.domain.Checks;
 import org.jclouds.vcloud.director.v1_5.domain.Metadata;
-import org.jclouds.vcloud.director.v1_5.domain.MetadataEntry;
-import org.jclouds.vcloud.director.v1_5.domain.MetadataValue;
 import org.jclouds.vcloud.director.v1_5.domain.Task;
 import org.jclouds.vcloud.director.v1_5.features.MetadataApi;
 import org.jclouds.vcloud.director.v1_5.features.VdcApi;
@@ -37,6 +35,8 @@
 import org.testng.annotations.BeforeClass;
 import org.testng.annotations.Test;
 
+import com.google.common.collect.ImmutableMap;
+
 /**
  * Tests behavior of {@link VdcApi}
  * 
@@ -67,7 +67,7 @@
    public void cleanUp() throws Exception {
       if (metadataKey != null) {
          try {
-            Task task = metadataApi.removeEntry(metadataKey);
+            Task task = metadataApi.remove(metadataKey);
             taskDoneEventually(task);
          } catch (VCloudDirectorException e) {
             logger.warn(e, "Error deleting metadata-value (perhaps it doesn't exist?); continuing...");
@@ -171,36 +171,33 @@
    public void testSetMetadata() throws Exception {
       metadataKey = name("key-");
       metadataValue = name("value-");
-      Metadata metadata = Metadata.builder().entry(MetadataEntry.builder().entry(metadataKey, metadataValue).build())
-               .build();
 
-      Task task = metadataApi.merge(metadata);
+      Task task = metadataApi.putAll(ImmutableMap.of(metadataKey, metadataValue));
+      
       assertTaskSucceeds(task);
 
-      MetadataValue modified = metadataApi.getValue(metadataKey);
-      Checks.checkMetadataValueFor("AdminVdc", modified, metadataValue);
-      Checks.checkMetadata(metadata);
+      String modified = metadataApi.get(metadataKey);
+      assertEquals(modified, metadataValue);
    }
 
    // TODO insufficient permissions to test
    @Test(description = "GET /admin/vdc/{id}/metadata/{key}", dependsOnMethods = { "testSetMetadata" }, enabled = false)
    public void testGetMetadataValue() throws Exception {
-      MetadataValue retrievedMetadataValue = metadataApi.getValue(metadataKey);
+      String retrievedMetadataValue = metadataApi.get(metadataKey);
 
-      Checks.checkMetadataValueFor("AdminVdc", retrievedMetadataValue, metadataValue);
+      assertEquals(retrievedMetadataValue, metadataValue);
    }
 
    // TODO insufficient permissions to test
    @Test(description = "PUT /admin/vdc/{id}/metadata/{key}", dependsOnMethods = { "testGetMetadataValue" }, enabled = false)
    public void testSetMetadataValue() throws Exception {
       metadataValue = name("value-");
-      MetadataValue newV = MetadataValue.builder().value(metadataValue).build();
 
-      Task task = metadataApi.putEntry(metadataKey, newV);
+      Task task = metadataApi.put(metadataKey, metadataValue);
       assertTaskSucceeds(task);
 
-      MetadataValue retrievedMetadataValue = metadataApi.getValue(metadataKey);
-      Checks.checkMetadataValueFor("AdminVdc", retrievedMetadataValue, metadataValue);
+      String retrievedMetadataValue = metadataApi.get(metadataKey);
+      assertEquals(retrievedMetadataValue, metadataValue);
    }
 
    // TODO insufficient permissions to test
@@ -208,14 +205,9 @@
    public void testRemoveMetadataValue() throws Exception {
       // TODO Remove dependency on other tests; make cleanUp remove a list of metadata entries?
 
-      Task task = metadataApi.removeEntry(metadataKey);
+      Task task = metadataApi.remove(metadataKey);
       assertTaskSucceeds(task);
 
-      try {
-         metadataApi.getValue(metadataKey);
-         fail("Retrieval of metadata value " + metadataKey + " should have fail after deletion");
-      } catch (VCloudDirectorException e) {
-         // success; should not be accessible
-      }
+      assertNull(metadataApi.get(metadataKey));
    }
 }
diff --git a/labs/vcloud-director/src/test/java/org/jclouds/vcloud/director/v1_5/features/systemadmin/SystemAdminVAppApiExpectTest.java b/labs/vcloud-director/src/test/java/org/jclouds/vcloud/director/v1_5/features/systemadmin/SystemAdminVAppApiExpectTest.java
new file mode 100644
index 0000000..3430a42
--- /dev/null
+++ b/labs/vcloud-director/src/test/java/org/jclouds/vcloud/director/v1_5/features/systemadmin/SystemAdminVAppApiExpectTest.java
@@ -0,0 +1,525 @@
+/*
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ *(Link.builder().regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless(Link.builder().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.vcloud.director.v1_5.features.systemadmin;
+
+import java.net.URI;
+
+import org.jclouds.dmtf.ovf.NetworkSection;
+import org.jclouds.dmtf.ovf.StartupSection;
+import org.jclouds.vcloud.director.v1_5.domain.Error;
+import org.jclouds.vcloud.director.v1_5.domain.Link;
+import org.jclouds.vcloud.director.v1_5.domain.Owner;
+import org.jclouds.vcloud.director.v1_5.domain.ProductSectionList;
+import org.jclouds.vcloud.director.v1_5.domain.RasdItemsList;
+import org.jclouds.vcloud.director.v1_5.domain.Reference;
+import org.jclouds.vcloud.director.v1_5.domain.ScreenTicket;
+import org.jclouds.vcloud.director.v1_5.domain.Task;
+import org.jclouds.vcloud.director.v1_5.domain.VApp;
+import org.jclouds.vcloud.director.v1_5.domain.VmPendingQuestion;
+import org.jclouds.vcloud.director.v1_5.domain.VmQuestionAnswer;
+import org.jclouds.vcloud.director.v1_5.domain.dmtf.RasdItem;
+import org.jclouds.vcloud.director.v1_5.domain.params.ControlAccessParams;
+import org.jclouds.vcloud.director.v1_5.domain.section.GuestCustomizationSection;
+import org.jclouds.vcloud.director.v1_5.domain.section.LeaseSettingsSection;
+import org.jclouds.vcloud.director.v1_5.domain.section.NetworkConfigSection;
+import org.jclouds.vcloud.director.v1_5.domain.section.NetworkConnectionSection;
+import org.jclouds.vcloud.director.v1_5.domain.section.OperatingSystemSection;
+import org.jclouds.vcloud.director.v1_5.domain.section.RuntimeInfoSection;
+import org.jclouds.vcloud.director.v1_5.domain.section.VirtualHardwareSection;
+import org.jclouds.vcloud.director.v1_5.features.VAppApi;
+import org.jclouds.vcloud.director.v1_5.internal.VCloudDirectorAdminApiExpectTest;
+import org.jclouds.vcloud.director.v1_5.user.VCloudDirectorApi;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+import org.testng.internal.annotations.Sets;
+
+/**
+ * Allows us to test the {@link VAppApi} allowed to system administrators
+ * 
+ * @author andrea turli
+ */
+@Test(groups = { "unit", "systemAdmin" }, singleThreaded = true, testName = "SystemAdminVAppApiExpectTest")
+public class SystemAdminVAppApiExpectTest extends VCloudDirectorAdminApiExpectTest {
+   
+   private String vAppId = "vapp-d0e2b6b9-4381-4ddc-9572-cdfae54059be";
+   private URI vAppURI = URI.create(endpoint + vAppId);
+   
+   @BeforeClass
+   public void before() {
+   }
+   
+   @Test(enabled = false)
+   public void testEnterMaintenanceMode() {
+      VCloudDirectorApi api = requestsSendResponses(loginRequest, sessionResponse, 
+         new VcloudHttpRequestPrimer()
+            .apiCommand("POST", vAppId + "/action/enterMaintenanceMode")
+            .acceptAnyMedia()
+            .httpRequestBuilder().build(), 
+         new VcloudHttpResponsePrimer()
+            .httpResponseBuilder().statusCode(204).build());
+		
+		// TODO how to test?
+		api.getVAppApi().enterMaintenanceMode(vAppURI);
+   }
+
+   @Test(enabled = false)
+   public void testExitMaintenanceMode() {
+      VCloudDirectorApi api = requestsSendResponses(loginRequest, sessionResponse, 
+         new VcloudHttpRequestPrimer()
+            .apiCommand("POST", vAppId + "/action/exitMaintenanceMode")
+            .acceptAnyMedia()
+            .httpRequestBuilder().build(), 
+         new VcloudHttpResponsePrimer()
+            .httpResponseBuilder().statusCode(204).build());
+		
+		// TODO how to test?
+		api.getVAppApi().exitMaintenanceMode(vAppURI);
+   }
+
+   public static VApp getVApp() {
+      // FIXME Does not match XML
+      VApp vApp = VApp.builder()
+            .href(URI.create("https://mycloud.greenhousedata.com/api/vApp/vapp-d0e2b6b9-4381-4ddc-9572-cdfae54059be"))
+//            .link(Link.builder()
+//                     .href(URI.create())
+//                     .build())
+            .build();
+
+//      <Link rel="power:powerOn" href="https://mycloud.greenhousedata.com/api/vApp/vapp-d0e2b6b9-4381-4ddc-9572-cdfae54059be/power/action/powerOn"/>
+//      <Link rel="deploy" type="application/vnd.vmware.vcloud.deployVAppParams+xml" href="https://mycloud.greenhousedata.com/api/vApp/vapp-d0e2b6b9-4381-4ddc-9572-cdfae54059be/action/deploy"/>
+//      <Link rel="down" type="application/vnd.vmware.vcloud.vAppNetwork+xml" name="orgNet-cloudsoft-External" href="https://mycloud.greenhousedata.com/api/network/2a2e2da4-446a-4ebc-a086-06df7c9570f0"/>
+//      <Link rel="down" type="application/vnd.vmware.vcloud.controlAccess+xml" href="https://mycloud.greenhousedata.com/api/vApp/vapp-d0e2b6b9-4381-4ddc-9572-cdfae54059be/controlAccess/"/>
+//      <Link rel="controlAccess" type="application/vnd.vmware.vcloud.controlAccess+xml" href="https://mycloud.greenhousedata.com/api/vApp/vapp-d0e2b6b9-4381-4ddc-9572-cdfae54059be/action/controlAccess"/>
+//      <Link rel="recompose" type="application/vnd.vmware.vcloud.recomposeVAppParams+xml" href="https://mycloud.greenhousedata.com/api/vApp/vapp-d0e2b6b9-4381-4ddc-9572-cdfae54059be/action/recomposeVApp"/>
+//      <Link rel="up" type="application/vnd.vmware.vcloud.vdc+xml" href="https://mycloud.greenhousedata.com/api/vdc/e9cd3387-ac57-4d27-a481-9bee75e0690f"/>
+//      <Link rel="edit" type="application/vnd.vmware.vcloud.vApp+xml" href="https://mycloud.greenhousedata.com/api/vApp/vapp-d0e2b6b9-4381-4ddc-9572-cdfae54059be"/>
+//      <Link rel="remove" href="https://mycloud.greenhousedata.com/api/vApp/vapp-d0e2b6b9-4381-4ddc-9572-cdfae54059be"/>
+//      <Link rel="down" type="application/vnd.vmware.vcloud.owner+xml" href="https://mycloud.greenhousedata.com/api/vApp/vapp-d0e2b6b9-4381-4ddc-9572-cdfae54059be/owner"/>
+//      <Link rel="down" type="application/vnd.vmware.vcloud.metadata+xml" href="https://mycloud.greenhousedata.com/api/vApp/vapp-d0e2b6b9-4381-4ddc-9572-cdfae54059be/metadata"/>
+      
+      return vApp;
+   }
+
+   public static Task editVAppTask() {
+      Task task = Task.builder()
+            .build();
+
+      return task;
+   }
+
+   public static Task removeVAppTask() {
+      Task task = Task.builder()
+            .build();
+
+      return task;
+   }
+
+   public static Task consolidateVAppTask() {
+      Task task = Task.builder()
+            .build();
+
+      return task;
+   }
+
+   public static ControlAccessParams controlAccessParams() {
+      ControlAccessParams params = ControlAccessParams.builder()
+            .build();
+
+      return params;
+   }
+
+   public static Task deployTask() {
+      Task task = Task.builder()
+            .build();
+
+      return task;
+   }
+
+   public static Task discardSuspendedStateTask() {
+      Task task = Task.builder()
+            .build();
+
+      return task;
+   }
+
+   public static Task installVMwareToolsTask() {
+      Task task = Task.builder()
+            .build();
+
+      return task;
+   }
+
+   public static Task recomposeVAppTask() {
+      Task task = Task.builder()
+            .build();
+
+      return task;
+   }
+
+   public static Task relocateTask() {
+      Task task = Task.builder()
+            .build();
+
+      return task;
+   }
+
+   public static Task undeployTask() {
+      Task task = Task.builder()
+            .build();
+
+      return task;
+   }
+
+   public static Task upgradeHardwareVersionTask() {
+      Task task = Task.builder()
+            .build();
+
+      return task;
+   }
+
+   public static Task powerOffTask() {
+      Task task = Task.builder()
+            .build();
+
+      return task;
+   }
+
+   public static Task powerOnTask() {
+      Task task = Task.builder()
+            .build();
+
+      return task;
+   }
+
+   public static Task rebootTask() {
+      Task task = Task.builder()
+            .build();
+
+      return task;
+   }
+
+   public static Task resetTask() {
+      Task task = Task.builder()
+            .build();
+
+      return task;
+   }
+
+   public static Task shutdownTask() {
+      Task task = Task.builder()
+            .build();
+
+      return task;
+   }
+
+   public static Task suspendTask() {
+      Task task = Task.builder()
+            .build();
+
+      return task;
+   }
+
+   public static ControlAccessParams getAccessControlParams() {
+      ControlAccessParams params = ControlAccessParams.builder()
+            .build();
+
+      return params;
+   }
+
+   public static GuestCustomizationSection getGuestCustomizationSection() {
+      GuestCustomizationSection section = GuestCustomizationSection.builder()
+            .build();
+
+      return section;
+   }
+
+   public static Task editGuestCustomizationSectionTask() {
+      Task task = Task.builder()
+            .build();
+
+      return task;
+   }
+
+   public static LeaseSettingsSection getLeaseSettingsSection() {
+      LeaseSettingsSection section = LeaseSettingsSection.builder()
+            .build();
+
+      return section;
+   }
+
+   public static Task editLeaseSettingsSectionTask() {
+      Task task = Task.builder()
+            .build();
+
+      return task;
+   }
+
+   public static Task ejectMediaTask() {
+      Task task = Task.builder()
+            .build();
+
+      return task;
+   }
+
+   public static Task insertMediaTask() {
+      Task task = Task.builder()
+            .build();
+
+      return task;
+   }
+
+   public static NetworkConfigSection getNetworkConfigSection() {
+      NetworkConfigSection section = NetworkConfigSection.builder()
+            .build();
+
+      return section;
+   }
+
+   public static Task editNetworkConfigSectionTask() {
+      Task task = Task.builder()
+            .build();
+
+      return task;
+   }
+
+   public static NetworkConnectionSection getNetworkConnectionSection() {
+      NetworkConnectionSection section = NetworkConnectionSection.builder()
+            .build();
+
+      return section;
+   }
+
+   public static Task editNetworkConnectionSectionTask() {
+      Task task = Task.builder()
+            .build();
+
+      return task;
+   }
+
+   public static NetworkSection getNetworkSection() {
+      NetworkSection section = NetworkSection.builder()
+            .build();
+
+      return section;
+   }
+
+   public static OperatingSystemSection getOperatingSystemSection() {
+      OperatingSystemSection section = OperatingSystemSection.builder()
+            .build();
+
+      return section;
+   }
+
+   public static Task editOperatingSystemSectionTask() {
+      Task task = Task.builder()
+            .build();
+
+      return task;
+   }
+
+   public static Owner getOwner() {
+      Owner owner = Owner.builder()
+            .build();
+
+      return owner;
+   }
+
+   public static Task editOwnerTask() {
+      Task task = Task.builder()
+            .build();
+
+      return task;
+   }
+
+   public static ProductSectionList getProductSections() {
+      ProductSectionList sectionItems = ProductSectionList.builder()
+            .build();
+
+      return sectionItems;
+   }
+
+   public static Task editProductSectionsTask() {
+      Task task = Task.builder()
+            .build();
+
+      return task;
+   }
+
+   public static VmPendingQuestion getPendingQuestion() {
+      VmPendingQuestion question = VmPendingQuestion.builder()
+            .build();
+
+      return question;
+   }
+
+   public static VmQuestionAnswer answerQuestion() {
+      VmQuestionAnswer answer = null; // = VmQuestionAnswer.builder() 
+//            .build();
+
+      return answer;
+   }
+
+   public static RuntimeInfoSection getRuntimeInfoSection() {
+      RuntimeInfoSection section = RuntimeInfoSection.builder()
+            .build();
+
+      return section;
+   }
+
+   public static byte[] getScreenImage() {
+      byte[] image = new byte[0];
+
+      return image;
+   }
+
+   public static ScreenTicket getScreenTicket() {
+      ScreenTicket ticket = null; // = ScreenTicket.builder();
+//            .build();
+
+      return ticket;
+   }
+
+   public static StartupSection getStartupSection() {
+      StartupSection section = null; // = StartupSection.builder();
+//            .build();
+
+      return section;
+   }
+
+   public static Task editStartupSectionTask() {
+      Task task = Task.builder()
+            .build();
+
+      return task;
+   }
+
+   public static VirtualHardwareSection getVirtualHardwareSection() {
+      VirtualHardwareSection section = VirtualHardwareSection.builder()
+            .build();
+
+      return section;
+   }
+
+   public static Task editVirtualHardwareSectionTask() {
+      Task task = Task.builder()
+            .build();
+
+      return task;
+   }
+
+   public static RasdItem getVirtualHardwareSectionCpu() {
+      RasdItem cpu = RasdItem.builder()
+            .build();
+
+      return cpu;
+   }
+
+   public static Task editVirtualHardwareSectionCpuTask() {
+      Task task = Task.builder()
+            .build();
+
+      return task;
+   }
+
+   public static RasdItemsList getVirtualHardwareSectionDisks() {
+      RasdItemsList disks = RasdItemsList.builder()
+            .build();
+
+      return disks;
+   }
+
+   public static Task editVirtualHardwareSectionDisksTask() {
+      Task task = Task.builder()
+            .build();
+
+      return task;
+   }
+
+   public static RasdItemsList getVirtualHardwareSectionMedia() {
+      RasdItemsList media = RasdItemsList.builder()
+            .build();
+
+      return media;
+   }
+
+   public static RasdItem getVirtualHardwareSectionMemory() {
+      RasdItem memory = RasdItem.builder()
+            .build();
+
+      return memory;
+   }
+
+   public static Task editVirtualHardwareSectionMemoryTask() {
+      Task task = Task.builder()
+            .build();
+
+      return task;
+   }
+
+   public static RasdItemsList getVirtualHardwareSectionNetworkCards() {
+      RasdItemsList networkCards = RasdItemsList.builder()
+            .build();
+
+      return networkCards;
+   }
+
+   public static Task editVirtualHardwareSectionNetworkCardsTask() {
+      Task task = Task.builder()
+            .build();
+
+      return task;
+   }
+
+   public static RasdItemsList getVirtualHardwareSectionSerialPorts() {
+      RasdItemsList serialPorts = RasdItemsList.builder()
+            .build();
+
+      return serialPorts;
+   }
+
+   public static Task editVirtualHardwareSectionSerialPortsTask() {
+      return task("id", "name", "description", "status", "operation", "operationName", "startTime");
+   }
+
+   /** Used by other methods to add a custom {@link Task} object. */
+   private static Task task(String taskId, String name, String description, String status, String operation, String operationName, String startTime) {
+      Task task = Task.builder()
+            .error(Error.builder().build())
+            .org(Reference.builder().build())
+            .owner(Reference.builder().build())
+            .user(Reference.builder().build())
+            .params(null)
+            .progress(0)
+            .status(status)
+            .operation(operation)
+            .operationName(operationName)
+            .startTime(dateService.iso8601DateParse(startTime))
+            .endTime(null)
+            .expiryTime(null)
+            .tasks(Sets.<Task>newLinkedHashSet())
+            .description(description)
+            .name(name)
+            .id("urn:vcloud:" + taskId)
+            .href(URI.create(endpoint + "/task/" + taskId))
+            .links(Sets.<Link>newLinkedHashSet())
+            .build();
+
+      return task;
+   }
+}
\ No newline at end of file
diff --git a/labs/vcloud-director/src/test/java/org/jclouds/vcloud/director/v1_5/features/systemadmin/SystemAdminVAppApiLiveTest.java b/labs/vcloud-director/src/test/java/org/jclouds/vcloud/director/v1_5/features/systemadmin/SystemAdminVAppApiLiveTest.java
new file mode 100644
index 0000000..94f5988
--- /dev/null
+++ b/labs/vcloud-director/src/test/java/org/jclouds/vcloud/director/v1_5/features/systemadmin/SystemAdminVAppApiLiveTest.java
@@ -0,0 +1,117 @@
+/*
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ *(Link.builder().regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless(Link.builder().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.vcloud.director.v1_5.features.systemadmin;
+
+import static org.jclouds.vcloud.director.v1_5.VCloudDirectorLiveTestConstants.CONDITION_FMT;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertTrue;
+
+import java.util.concurrent.TimeUnit;
+
+import org.jclouds.vcloud.director.v1_5.AbstractVAppApiLiveTest;
+import org.jclouds.vcloud.director.v1_5.domain.Task;
+import org.jclouds.vcloud.director.v1_5.domain.VApp;
+import org.jclouds.vcloud.director.v1_5.domain.params.DeployVAppParams;
+import org.jclouds.vcloud.director.v1_5.features.VAppApi;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+/**
+ * Allows us to test the {@link VAppApi} allowed to system administrators
+ * 
+ * @author andrea turli
+ */
+@Test(singleThreaded = true, testName = "SystemAdminVAppApiLiveTest")
+public class SystemAdminVAppApiLiveTest extends AbstractVAppApiLiveTest {
+
+   private boolean testUserCreated = false;
+
+   @BeforeClass(alwaysRun = true)
+   protected void setupRequiredEntities() {
+
+      if (adminContext != null) {
+         userUrn = adminContext.getApi().getUserApi().addUserToOrg(randomTestUser("VAppAccessTest"), org.getId())
+                  .getId();
+      }
+   }
+
+   @AfterClass(alwaysRun = true, dependsOnMethods = { "cleanUpEnvironment" })
+   public void cleanUp() {
+      if (adminContext != null && testUserCreated && userUrn != null) {
+         try {
+            adminContext.getApi().getUserApi().remove(userUrn);
+         } catch (Exception e) {
+            logger.warn(e, "Error when deleting user");
+         }
+      }
+   }
+
+   @Test(description = "POST /vApp/{id}/action/enterMaintenanceMode", groups = { "systemAdmin" })
+   public void testEnterMaintenanceMode() {
+
+      // Do this to a new vApp, so don't mess up subsequent tests by making the vApp read-only
+      VApp temp = instantiateVApp();
+      DeployVAppParams params = DeployVAppParams.builder()
+               .deploymentLeaseSeconds((int) TimeUnit.SECONDS.convert(1L, TimeUnit.HOURS)).notForceCustomization()
+               .notPowerOn().build();
+      Task deployVApp = vAppApi.deploy(temp.getId(), params);
+      assertTaskSucceedsLong(deployVApp);
+
+      try {
+         // Method under test
+         vAppApi.enterMaintenanceMode(temp.getId());
+
+         temp = vAppApi.get(temp.getId());
+         assertTrue(temp.isInMaintenanceMode(),
+                  String.format(CONDITION_FMT, "InMaintenanceMode", "TRUE", temp.isInMaintenanceMode()));
+
+         // Exit maintenance mode
+         vAppApi.exitMaintenanceMode(temp.getId());
+      } finally {
+         cleanUpVApp(temp);
+      }
+   }
+
+   @Test(description = "POST /vApp/{id}/action/exitMaintenanceMode", dependsOnMethods = { "testEnterMaintenanceMode" }, groups = { "systemAdmin" })
+   public void testExitMaintenanceMode() {
+      // Do this to a new vApp, so don't mess up subsequent tests by making the vApp read-only
+      VApp temp = instantiateVApp();
+      DeployVAppParams params = DeployVAppParams.builder()
+               .deploymentLeaseSeconds((int) TimeUnit.SECONDS.convert(1L, TimeUnit.HOURS)).notForceCustomization()
+               .notPowerOn().build();
+      Task deployVApp = vAppApi.deploy(temp.getId(), params);
+      assertTaskSucceedsLong(deployVApp);
+
+      try {
+         // Enter maintenance mode
+         vAppApi.enterMaintenanceMode(temp.getId());
+
+         // Method under test
+         vAppApi.exitMaintenanceMode(temp.getId());
+
+         temp = vAppApi.get(temp.getId());
+         assertFalse(temp.isInMaintenanceMode(),
+                  String.format(CONDITION_FMT, "InMaintenanceMode", "FALSE", temp.isInMaintenanceMode()));
+      } finally {
+         cleanUpVApp(temp);
+      }
+   }
+
+}
\ No newline at end of file
diff --git a/labs/vcloud-director/src/test/java/org/jclouds/vcloud/director/v1_5/features/systemadmin/SystemAdminVmApiExpectTest.java b/labs/vcloud-director/src/test/java/org/jclouds/vcloud/director/v1_5/features/systemadmin/SystemAdminVmApiExpectTest.java
new file mode 100644
index 0000000..648c408
--- /dev/null
+++ b/labs/vcloud-director/src/test/java/org/jclouds/vcloud/director/v1_5/features/systemadmin/SystemAdminVmApiExpectTest.java
@@ -0,0 +1,522 @@
+/*
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ *(Link.builder().regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless(Link.builder().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.vcloud.director.v1_5.features.systemadmin;
+
+import static org.testng.Assert.assertEquals;
+
+import java.net.URI;
+
+import org.jclouds.dmtf.ovf.NetworkSection;
+import org.jclouds.dmtf.ovf.StartupSection;
+import org.jclouds.vcloud.director.v1_5.VCloudDirectorMediaType;
+import org.jclouds.vcloud.director.v1_5.domain.Error;
+import org.jclouds.vcloud.director.v1_5.domain.Link;
+import org.jclouds.vcloud.director.v1_5.domain.Owner;
+import org.jclouds.vcloud.director.v1_5.domain.ProductSectionList;
+import org.jclouds.vcloud.director.v1_5.domain.RasdItemsList;
+import org.jclouds.vcloud.director.v1_5.domain.Reference;
+import org.jclouds.vcloud.director.v1_5.domain.ScreenTicket;
+import org.jclouds.vcloud.director.v1_5.domain.Task;
+import org.jclouds.vcloud.director.v1_5.domain.Vm;
+import org.jclouds.vcloud.director.v1_5.domain.VmPendingQuestion;
+import org.jclouds.vcloud.director.v1_5.domain.VmQuestionAnswer;
+import org.jclouds.vcloud.director.v1_5.domain.dmtf.RasdItem;
+import org.jclouds.vcloud.director.v1_5.domain.params.ControlAccessParams;
+import org.jclouds.vcloud.director.v1_5.domain.params.RelocateParams;
+import org.jclouds.vcloud.director.v1_5.domain.section.GuestCustomizationSection;
+import org.jclouds.vcloud.director.v1_5.domain.section.LeaseSettingsSection;
+import org.jclouds.vcloud.director.v1_5.domain.section.NetworkConfigSection;
+import org.jclouds.vcloud.director.v1_5.domain.section.NetworkConnectionSection;
+import org.jclouds.vcloud.director.v1_5.domain.section.OperatingSystemSection;
+import org.jclouds.vcloud.director.v1_5.domain.section.RuntimeInfoSection;
+import org.jclouds.vcloud.director.v1_5.domain.section.VirtualHardwareSection;
+import org.jclouds.vcloud.director.v1_5.features.VmApi;
+import org.jclouds.vcloud.director.v1_5.internal.VCloudDirectorAdminApiExpectTest;
+import org.jclouds.vcloud.director.v1_5.user.VCloudDirectorApi;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+import org.testng.internal.annotations.Sets;
+
+/**
+ * Allows us to test the {@link VmApi} allowed to system administrators
+ * 
+ * @author andrea turli
+ */
+@Test(groups = { "unit", "systemAdmin" }, singleThreaded = true, testName = "SystemAdminVmApiExpectTest")
+public class SystemAdminVmApiExpectTest extends VCloudDirectorAdminApiExpectTest {
+   
+   private String vmId = "vm-d0e2b6b9-4381-4ddc-9572-cdfae54059be";
+   private URI vmURI = URI.create(endpoint + vmId);
+   
+   @BeforeClass
+   public void before() {
+   }
+   
+   @Test(enabled = false)
+   public void testRelocate() {
+      VCloudDirectorApi api = requestsSendResponses(loginRequest, sessionResponse, 
+         new VcloudHttpRequestPrimer()
+            .apiCommand("POST", vmId + "/action/relocate")
+            .xmlFilePayload("/vApp/relocateParams.xml", VCloudDirectorMediaType.RELOCATE_VM_PARAMS)
+            .acceptAnyMedia()
+            .httpRequestBuilder().build(), 
+         new VcloudHttpResponsePrimer()
+            .xmlFilePayload("/vApp/relocateTask.xml", VCloudDirectorMediaType.TASK)
+            .httpResponseBuilder().build());
+     
+      RelocateParams params = RelocateParams.builder()
+            .build();
+		
+		Task expected = relocateTask();
+		
+		assertEquals(api.getVmApi().relocate(vmURI, params), expected);
+   }
+   
+
+   public static Vm getVm() {
+      // FIXME Does not match XML
+      Vm vm = Vm.builder()
+            .href(URI.create("https://mycloud.greenhousedata.com/api/vApp/vm-d0e2b6b9-4381-4ddc-9572-cdfae54059be"))
+//            .link(Link.builder()
+//                     .href(URI.create())
+//                     .build())
+            .build();
+
+//      <Link rel="power:powerOn" href="https://mycloud.greenhousedata.com/api/vApp/vapp-d0e2b6b9-4381-4ddc-9572-cdfae54059be/power/action/powerOn"/>
+//      <Link rel="deploy" type="application/vnd.vmware.vcloud.deployVAppParams+xml" href="https://mycloud.greenhousedata.com/api/vApp/vapp-d0e2b6b9-4381-4ddc-9572-cdfae54059be/action/deploy"/>
+//      <Link rel="down" type="application/vnd.vmware.vcloud.vAppNetwork+xml" name="orgNet-cloudsoft-External" href="https://mycloud.greenhousedata.com/api/network/2a2e2da4-446a-4ebc-a086-06df7c9570f0"/>
+//      <Link rel="down" type="application/vnd.vmware.vcloud.controlAccess+xml" href="https://mycloud.greenhousedata.com/api/vApp/vapp-d0e2b6b9-4381-4ddc-9572-cdfae54059be/controlAccess/"/>
+//      <Link rel="controlAccess" type="application/vnd.vmware.vcloud.controlAccess+xml" href="https://mycloud.greenhousedata.com/api/vApp/vapp-d0e2b6b9-4381-4ddc-9572-cdfae54059be/action/controlAccess"/>
+//      <Link rel="recompose" type="application/vnd.vmware.vcloud.recomposeVAppParams+xml" href="https://mycloud.greenhousedata.com/api/vApp/vapp-d0e2b6b9-4381-4ddc-9572-cdfae54059be/action/recomposeVApp"/>
+//      <Link rel="up" type="application/vnd.vmware.vcloud.vdc+xml" href="https://mycloud.greenhousedata.com/api/vdc/e9cd3387-ac57-4d27-a481-9bee75e0690f"/>
+//      <Link rel="edit" type="application/vnd.vmware.vcloud.vApp+xml" href="https://mycloud.greenhousedata.com/api/vApp/vapp-d0e2b6b9-4381-4ddc-9572-cdfae54059be"/>
+//      <Link rel="remove" href="https://mycloud.greenhousedata.com/api/vApp/vapp-d0e2b6b9-4381-4ddc-9572-cdfae54059be"/>
+//      <Link rel="down" type="application/vnd.vmware.vcloud.owner+xml" href="https://mycloud.greenhousedata.com/api/vApp/vapp-d0e2b6b9-4381-4ddc-9572-cdfae54059be/owner"/>
+//      <Link rel="down" type="application/vnd.vmware.vcloud.metadata+xml" href="https://mycloud.greenhousedata.com/api/vApp/vapp-d0e2b6b9-4381-4ddc-9572-cdfae54059be/metadata"/>
+      
+      return vm;
+   }
+
+   public static Task editVmTask() {
+      Task task = Task.builder()
+            .build();
+
+      return task;
+   }
+
+   public static Task removeVmTask() {
+      Task task = Task.builder()
+            .build();
+
+      return task;
+   }
+
+   public static Task consolidateVmTask() {
+      Task task = Task.builder()
+            .build();
+
+      return task;
+   }
+
+   public static ControlAccessParams controlAccessParams() {
+      ControlAccessParams params = ControlAccessParams.builder()
+            .build();
+
+      return params;
+   }
+
+   public static Task deployTask() {
+      Task task = Task.builder()
+            .build();
+
+      return task;
+   }
+
+   public static Task discardSuspendedStateTask() {
+      Task task = Task.builder()
+            .build();
+
+      return task;
+   }
+
+   public static Task installVMwareToolsTask() {
+      Task task = Task.builder()
+            .build();
+
+      return task;
+   }
+
+   public static Task recomposeVmTask() {
+      Task task = Task.builder()
+            .build();
+
+      return task;
+   }
+
+   public static Task relocateTask() {
+      Task task = Task.builder()
+            .build();
+
+      return task;
+   }
+
+   public static Task undeployTask() {
+      Task task = Task.builder()
+            .build();
+
+      return task;
+   }
+
+   public static Task upgradeHardwareVersionTask() {
+      Task task = Task.builder()
+            .build();
+
+      return task;
+   }
+
+   public static Task powerOffTask() {
+      Task task = Task.builder()
+            .build();
+
+      return task;
+   }
+
+   public static Task powerOnTask() {
+      Task task = Task.builder()
+            .build();
+
+      return task;
+   }
+
+   public static Task rebootTask() {
+      Task task = Task.builder()
+            .build();
+
+      return task;
+   }
+
+   public static Task resetTask() {
+      Task task = Task.builder()
+            .build();
+
+      return task;
+   }
+
+   public static Task shutdownTask() {
+      Task task = Task.builder()
+            .build();
+
+      return task;
+   }
+
+   public static Task suspendTask() {
+      Task task = Task.builder()
+            .build();
+
+      return task;
+   }
+
+   public static ControlAccessParams getAccessControlParams() {
+      ControlAccessParams params = ControlAccessParams.builder()
+            .build();
+
+      return params;
+   }
+
+   public static GuestCustomizationSection getGuestCustomizationSection() {
+      GuestCustomizationSection section = GuestCustomizationSection.builder()
+            .build();
+
+      return section;
+   }
+
+   public static Task editGuestCustomizationSectionTask() {
+      Task task = Task.builder()
+            .build();
+
+      return task;
+   }
+
+   public static LeaseSettingsSection getLeaseSettingsSection() {
+      LeaseSettingsSection section = LeaseSettingsSection.builder()
+            .build();
+
+      return section;
+   }
+
+   public static Task editLeaseSettingsSectionTask() {
+      Task task = Task.builder()
+            .build();
+
+      return task;
+   }
+
+   public static Task ejectMediaTask() {
+      Task task = Task.builder()
+            .build();
+
+      return task;
+   }
+
+   public static Task insertMediaTask() {
+      Task task = Task.builder()
+            .build();
+
+      return task;
+   }
+
+   public static NetworkConfigSection getNetworkConfigSection() {
+      NetworkConfigSection section = NetworkConfigSection.builder()
+            .build();
+
+      return section;
+   }
+
+   public static Task editNetworkConfigSectionTask() {
+      Task task = Task.builder()
+            .build();
+
+      return task;
+   }
+
+   public static NetworkConnectionSection getNetworkConnectionSection() {
+      NetworkConnectionSection section = NetworkConnectionSection.builder()
+            .build();
+
+      return section;
+   }
+
+   public static Task editNetworkConnectionSectionTask() {
+      Task task = Task.builder()
+            .build();
+
+      return task;
+   }
+
+   public static NetworkSection getNetworkSection() {
+      NetworkSection section = NetworkSection.builder()
+            .build();
+
+      return section;
+   }
+
+   public static OperatingSystemSection getOperatingSystemSection() {
+      OperatingSystemSection section = OperatingSystemSection.builder()
+            .build();
+
+      return section;
+   }
+
+   public static Task editOperatingSystemSectionTask() {
+      Task task = Task.builder()
+            .build();
+
+      return task;
+   }
+
+   public static Owner getOwner() {
+      Owner owner = Owner.builder()
+            .build();
+
+      return owner;
+   }
+
+   public static Task editOwnerTask() {
+      Task task = Task.builder()
+            .build();
+
+      return task;
+   }
+
+   public static ProductSectionList getProductSections() {
+      ProductSectionList sectionItems = ProductSectionList.builder()
+            .build();
+
+      return sectionItems;
+   }
+
+   public static Task editProductSectionsTask() {
+      Task task = Task.builder()
+            .build();
+
+      return task;
+   }
+
+   public static VmPendingQuestion getPendingQuestion() {
+      VmPendingQuestion question = VmPendingQuestion.builder()
+            .build();
+
+      return question;
+   }
+
+   public static VmQuestionAnswer answerQuestion() {
+      VmQuestionAnswer answer = null; // = VmQuestionAnswer.builder() 
+//            .build();
+
+      return answer;
+   }
+
+   public static RuntimeInfoSection getRuntimeInfoSection() {
+      RuntimeInfoSection section = RuntimeInfoSection.builder()
+            .build();
+
+      return section;
+   }
+
+   public static byte[] getScreenImage() {
+      byte[] image = new byte[0];
+
+      return image;
+   }
+
+   public static ScreenTicket getScreenTicket() {
+      ScreenTicket ticket = null; // = ScreenTicket.builder();
+//            .build();
+
+      return ticket;
+   }
+
+   public static StartupSection getStartupSection() {
+      StartupSection section = null; // = StartupSection.builder();
+//            .build();
+
+      return section;
+   }
+
+   public static Task editStartupSectionTask() {
+      Task task = Task.builder()
+            .build();
+
+      return task;
+   }
+
+   public static VirtualHardwareSection getVirtualHardwareSection() {
+      VirtualHardwareSection section = VirtualHardwareSection.builder()
+            .build();
+
+      return section;
+   }
+
+   public static Task editVirtualHardwareSectionTask() {
+      Task task = Task.builder()
+            .build();
+
+      return task;
+   }
+
+   public static RasdItem getVirtualHardwareSectionCpu() {
+      RasdItem cpu = RasdItem.builder()
+            .build();
+
+      return cpu;
+   }
+
+   public static Task editVirtualHardwareSectionCpuTask() {
+      Task task = Task.builder()
+            .build();
+
+      return task;
+   }
+
+   public static RasdItemsList getVirtualHardwareSectionDisks() {
+      RasdItemsList disks = RasdItemsList.builder()
+            .build();
+
+      return disks;
+   }
+
+   public static Task editVirtualHardwareSectionDisksTask() {
+      Task task = Task.builder()
+            .build();
+
+      return task;
+   }
+
+   public static RasdItemsList getVirtualHardwareSectionMedia() {
+      RasdItemsList media = RasdItemsList.builder()
+            .build();
+
+      return media;
+   }
+
+   public static RasdItem getVirtualHardwareSectionMemory() {
+      RasdItem memory = RasdItem.builder()
+            .build();
+
+      return memory;
+   }
+
+   public static Task editVirtualHardwareSectionMemoryTask() {
+      Task task = Task.builder()
+            .build();
+
+      return task;
+   }
+
+   public static RasdItemsList getVirtualHardwareSectionNetworkCards() {
+      RasdItemsList networkCards = RasdItemsList.builder()
+            .build();
+
+      return networkCards;
+   }
+
+   public static Task editVirtualHardwareSectionNetworkCardsTask() {
+      Task task = Task.builder()
+            .build();
+
+      return task;
+   }
+
+   public static RasdItemsList getVirtualHardwareSectionSerialPorts() {
+      RasdItemsList serialPorts = RasdItemsList.builder()
+            .build();
+
+      return serialPorts;
+   }
+
+   public static Task editVirtualHardwareSectionSerialPortsTask() {
+      return task("id", "name", "description", "status", "operation", "operationName", "startTime");
+   }
+
+   /** Used by other methods to add a custom {@link Task} object. */
+   private static Task task(String taskId, String name, String description, String status, String operation, String operationName, String startTime) {
+      Task task = Task.builder()
+            .error(Error.builder().build())
+            .org(Reference.builder().build())
+            .owner(Reference.builder().build())
+            .user(Reference.builder().build())
+            .params(null)
+            .progress(0)
+            .status(status)
+            .operation(operation)
+            .operationName(operationName)
+            .startTime(dateService.iso8601DateParse(startTime))
+            .endTime(null)
+            .expiryTime(null)
+            .tasks(Sets.<Task>newLinkedHashSet())
+            .description(description)
+            .name(name)
+            .id("urn:vcloud:" + taskId)
+            .href(URI.create(endpoint + "/task/" + taskId))
+            .links(Sets.<Link>newLinkedHashSet())
+            .build();
+
+      return task;
+   }
+}
\ No newline at end of file
diff --git a/labs/vcloud-director/src/test/java/org/jclouds/vcloud/director/v1_5/features/systemadmin/SystemAdminVmApiLiveTest.java b/labs/vcloud-director/src/test/java/org/jclouds/vcloud/director/v1_5/features/systemadmin/SystemAdminVmApiLiveTest.java
new file mode 100644
index 0000000..c061069
--- /dev/null
+++ b/labs/vcloud-director/src/test/java/org/jclouds/vcloud/director/v1_5/features/systemadmin/SystemAdminVmApiLiveTest.java
@@ -0,0 +1,136 @@
+/*
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ *(Link.builder().regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless(Link.builder().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.vcloud.director.v1_5.features.systemadmin;
+
+import static org.jclouds.vcloud.director.v1_5.VCloudDirectorLiveTestConstants.OBJ_FIELD_EQ;
+import static org.jclouds.vcloud.director.v1_5.VCloudDirectorLiveTestConstants.TASK_COMPLETE_TIMELY;
+import static org.jclouds.vcloud.director.v1_5.domain.Checks.checkVm;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+
+import java.util.concurrent.TimeUnit;
+
+import org.jclouds.vcloud.director.v1_5.AbstractVAppApiLiveTest;
+import org.jclouds.vcloud.director.v1_5.domain.Reference;
+import org.jclouds.vcloud.director.v1_5.domain.ResourceEntity.Status;
+import org.jclouds.vcloud.director.v1_5.domain.Task;
+import org.jclouds.vcloud.director.v1_5.domain.params.DeployVAppParams;
+import org.jclouds.vcloud.director.v1_5.domain.params.RelocateParams;
+import org.jclouds.vcloud.director.v1_5.domain.query.QueryResultRecordType;
+import org.jclouds.vcloud.director.v1_5.domain.query.QueryResultRecords;
+import org.jclouds.vcloud.director.v1_5.features.VmApi;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.Iterables;
+
+/**
+ * Tests behavior of the {@link VmApi}.
+ * 
+ * @author andrea turli
+ */
+@Test(groups = { "live", "systemAdmin" }, singleThreaded = true, testName = "SystemAdminVmApiLiveTest")
+public class SystemAdminVmApiLiveTest extends AbstractVAppApiLiveTest {
+
+   private boolean testUserCreated = false;
+
+   @BeforeClass(alwaysRun = true)
+   protected void setupRequiredEntities() {
+
+      if (adminContext != null) {
+         userUrn = adminContext.getApi().getUserApi().addUserToOrg(randomTestUser("VAppAccessTest"), org.getId())
+                  .getId();
+      }
+   }
+
+   @AfterClass(alwaysRun = true, dependsOnMethods = { "cleanUpEnvironment" })
+   public void cleanUp() {
+      if (adminContext != null && testUserCreated && userUrn != null) {
+         try {
+            adminContext.getApi().getUserApi().remove(userUrn);
+         } catch (Exception e) {
+            logger.warn("Error when deleting user: %s", e.getMessage());
+         }
+      }
+   }
+
+   /**
+    * @see VmApi#get(String)
+    */
+   @Test(description = "GET /vApp/{id}")
+   public void testGetVm() {
+      // The method under test
+      vm = vmApi.get(vmUrn);
+
+      // Check the retrieved object is well formed
+      checkVm(vm);
+
+      // Check the required fields are set
+      assertEquals(vm.isDeployed(), Boolean.FALSE,
+               String.format(OBJ_FIELD_EQ, VM, "deployed", "FALSE", vm.isDeployed().toString()));
+
+      // Check status
+      assertVmStatus(vmUrn, Status.POWERED_OFF);
+   }
+   
+   // NOTE This test is disabled, as it is not possible to look up datastores using the User API
+   @Test(description = "POST /vApp/{id}/action/relocate", dependsOnMethods = { "testGetVm" })
+   public void testRelocate() {
+      // Relocate to the last of the available datastores
+      QueryResultRecords records = adminContext.getApi().getQueryApi().queryAll("datastore");
+      QueryResultRecordType datastore = Iterables.getLast(records.getRecords());
+      RelocateParams params = RelocateParams.builder().datastore(Reference.builder().href(datastore.getHref()).build())
+               .build();
+
+      // The method under test
+      Task relocate = vmApi.relocate(vmUrn, params);
+      assertTrue(retryTaskSuccess.apply(relocate), String.format(TASK_COMPLETE_TIMELY, "relocate"));
+   }
+   
+   @Test(description = "POST /vApp/{id}/action/deploy", dependsOnMethods = { "testGetVm" })
+   public void testDeployVm() {
+      DeployVAppParams params = DeployVAppParams.builder()
+               .deploymentLeaseSeconds((int) TimeUnit.SECONDS.convert(1L, TimeUnit.HOURS)).notForceCustomization()
+               .notPowerOn().build();
+
+      // The method under test
+      Task deployVm = vmApi.deploy(vmUrn, params);
+      assertTrue(retryTaskSuccessLong.apply(deployVm), String.format(TASK_COMPLETE_TIMELY, "deployVm"));
+
+      // Get the edited Vm
+      vm = vmApi.get(vmUrn);
+
+      // Check the required fields are set
+      assertTrue(vm.isDeployed(), String.format(OBJ_FIELD_EQ, VM, "deployed", "TRUE", vm.isDeployed().toString()));
+
+      // Check status
+      assertVmStatus(vmUrn, Status.POWERED_OFF);
+   }   
+   
+   @Test(description = "POST /vApp/{id}/action/consolidate", dependsOnMethods = { "testDeployVm" })
+   public void testConsolidateVm() {
+      // Power on Vm
+      vm = powerOnVm(vmUrn);
+
+      // The method under test
+      Task consolidateVm = vmApi.consolidate(vmUrn);
+      assertTrue(retryTaskSuccess.apply(consolidateVm), String.format(TASK_COMPLETE_TIMELY, "consolidateVm"));
+   }
+}
\ No newline at end of file
diff --git a/labs/vcloud-director/src/test/java/org/jclouds/vcloud/director/v1_5/internal/BaseVCloudDirectorApiLiveTest.java b/labs/vcloud-director/src/test/java/org/jclouds/vcloud/director/v1_5/internal/BaseVCloudDirectorApiLiveTest.java
index 55fef1f..503b895 100644
--- a/labs/vcloud-director/src/test/java/org/jclouds/vcloud/director/v1_5/internal/BaseVCloudDirectorApiLiveTest.java
+++ b/labs/vcloud-director/src/test/java/org/jclouds/vcloud/director/v1_5/internal/BaseVCloudDirectorApiLiveTest.java
@@ -29,6 +29,7 @@
 import static org.jclouds.vcloud.director.v1_5.VCloudDirectorLiveTestConstants.TASK_COMPLETE_TIMELY;
 import static org.jclouds.vcloud.director.v1_5.VCloudDirectorLiveTestConstants.URN_REQ_LIVE;
 import static org.jclouds.vcloud.director.v1_5.VCloudDirectorMediaType.CATALOG;
+import static org.jclouds.vcloud.director.v1_5.VCloudDirectorMediaType.MEDIA;
 import static org.jclouds.vcloud.director.v1_5.VCloudDirectorMediaType.NETWORK;
 import static org.jclouds.vcloud.director.v1_5.VCloudDirectorMediaType.ORG_NETWORK;
 import static org.jclouds.vcloud.director.v1_5.VCloudDirectorMediaType.USER;
@@ -245,7 +246,7 @@
       networkUrn = emptyToNull(System.getProperty("test." + provider + ".network-id"));
 
       userUrn = emptyToNull(System.getProperty("test." + provider + ".user-id"));
-
+     
       org = context
                .getApi()
                .getOrgApi()
@@ -267,7 +268,6 @@
                vAppTemplateUrn = vAppTemplate.getId();
                }
             }
-
          }
 
          if (networkUrn == null) {
@@ -354,11 +354,10 @@
          public boolean apply(Vm input) {
             return input.getId() != null;
          }
-
       });
       
       if (optionalVm.isPresent()) {
-         Logger.CONSOLE.info("found vAppTemplate: %s", prettyVm.apply(optionalVm.get()));
+         Logger.CONSOLE.info("found vm: %s", prettyVm.apply(optionalVm.get()));
       } else {
          Logger.CONSOLE.warn("%s doesn't have any vm in org %s; vms: %s", context.getApi()
                   .getCurrentSession().getUser(), org.getName(), Iterables.transform(vms, prettyVm));
@@ -447,7 +446,52 @@
       }
       return optionalNetwork;
    }
+   
+	public FluentIterable<Media> findAllEmptyMediaInOrg() {
+		vdc = context.getApi().getVdcApi().get(vdc.getId());
+		return FluentIterable
+				.from(vdc.getResourceEntities())
+				.filter(ReferencePredicates.<Reference> typeEquals(MEDIA))
+				.transform(new Function<Reference, Media>() {
 
+					@Override
+					public Media apply(Reference in) {
+						return context.getApi().getMediaApi()
+								.get(in.getHref());
+					}
+				}).filter(new Predicate<Media>() {
+
+					@Override
+					public boolean apply(Media input) {
+						return input.getSize() == 0;
+					}
+				});
+	}
+	
+	public void cleanUpVAppTemplateInOrg() {
+		FluentIterable<VAppTemplate> vAppTemplates = FluentIterable
+				.from(vdc.getResourceEntities())
+				.filter(ReferencePredicates
+						.<Reference> typeEquals(VAPP_TEMPLATE))
+				.transform(new Function<Reference, VAppTemplate>() {
+
+					@Override
+					public VAppTemplate apply(Reference in) {
+						return context.getApi().getVAppTemplateApi()
+								.get(in.getHref());
+					}
+				}).filter(Predicates.notNull());
+
+		Iterables.removeIf(vAppTemplates, new Predicate<VAppTemplate>() {
+
+			@Override
+			public boolean apply(VAppTemplate input) {
+				if(input.getName().startsWith("captured-") || input.getName().startsWith("uploaded-") || input.getName().startsWith("vappTemplateClone-"))
+					context.getApi().getVAppTemplateApi().remove(input.getHref());
+				return false;
+			}});
+	}	
+	
    protected Vdc lazyGetVdc() {
       if (vdc == null) {
          assertNotNull(vdcUrn, String.format(URN_REQ_LIVE, VDC));
@@ -508,9 +552,9 @@
                assertTrue(retryTaskSuccess.apply(uploadTask), String.format(TASK_COMPLETE_TIMELY, "uploadTask"));
                media = context.getApi().getMediaApi().get(media.getId());
             }
-
             mediaUrn = media.getId();
-         }
+         } else 
+        	 media = context.getApi().getMediaApi().get(mediaUrn);
       }
       return media;
    }
@@ -676,10 +720,10 @@
          }
       }
 
-      // Shutdown and power off the VApp if necessary
+      // power off the VApp if necessary
       if (vApp.getStatus() == Status.POWERED_ON) {
          try {
-            Task shutdownTask = vAppApi.shutdown(vAppUrn);
+            Task shutdownTask = vAppApi.powerOff(vAppUrn);
             taskDoneEventually(shutdownTask);
          } catch (Exception e) {
             // keep going; cleanup as much as possible
diff --git a/labs/vcloud-director/src/test/java/org/jclouds/vcloud/director/v1_5/internal/BaseVCloudDirectorExpectTest.java b/labs/vcloud-director/src/test/java/org/jclouds/vcloud/director/v1_5/internal/BaseVCloudDirectorExpectTest.java
index 44c9d9c..8a6f3cd 100644
--- a/labs/vcloud-director/src/test/java/org/jclouds/vcloud/director/v1_5/internal/BaseVCloudDirectorExpectTest.java
+++ b/labs/vcloud-director/src/test/java/org/jclouds/vcloud/director/v1_5/internal/BaseVCloudDirectorExpectTest.java
@@ -234,7 +234,7 @@
    
    @Deprecated
    protected class VcloudHttpResponsePrimer {
-      private HttpResponse.Builder<?> builder = HttpResponse.builder();
+      private HttpResponse.Builder<?> builder = HttpResponse.builder().statusCode(200);
 
       public VcloudHttpResponsePrimer() {
       }
diff --git a/labs/vcloud-director/src/test/resources/vapptemplate/metadataValue.xml b/labs/vcloud-director/src/test/resources/vapptemplate/metadataValue.xml
index 96d29f2..df6649a 100644
--- a/labs/vcloud-director/src/test/resources/vapptemplate/metadataValue.xml
+++ b/labs/vcloud-director/src/test/resources/vapptemplate/metadataValue.xml
@@ -1,4 +1,3 @@
-<MetadataValue
-        xmlns="http://www.vmware.com/vcloud/v1.5">
+<MetadataValue xmlns="http://www.vmware.com/vcloud/v1.5">
     <Value>some value</Value>
 </MetadataValue>
\ No newline at end of file
diff --git a/labs/virtualbox/src/test/resources/.gitattributes b/labs/virtualbox/src/test/resources/.gitattributes
new file mode 100644
index 0000000..ba409ff
--- /dev/null
+++ b/labs/virtualbox/src/test/resources/.gitattributes
@@ -0,0 +1 @@
+*.sh -crlf
diff --git a/labs/virtualbox/src/test/resources/test_guest_additions_installer_init.sh b/labs/virtualbox/src/test/resources/test_guest_additions_installer_init.sh
index 34b794c..2d6320e 100644
--- a/labs/virtualbox/src/test/resources/test_guest_additions_installer_init.sh
+++ b/labs/virtualbox/src/test/resources/test_guest_additions_installer_init.sh
@@ -117,7 +117,7 @@
 
 # download locations for many services are at public dns
 function ensure_can_resolve_public_dns() {
-  nslookup yahoo.com > /dev/null || echo nameserver 208.67.222.222 >> /etc/resolv.conf
+  nslookup yahoo.com | grep yahoo.com > /dev/null || echo nameserver 208.67.222.222 >> /etc/resolv.conf
 }
 
 function setupPublicCurl() {
diff --git a/project/pom.xml b/project/pom.xml
index 37bf201..00b6ed7 100644
--- a/project/pom.xml
+++ b/project/pom.xml
@@ -368,6 +368,7 @@
                         <ignoredResource>amzn_images.xml</ignoredResource>
                         <ignoredResource>test.jks</ignoredResource>
                         <ignoredResource>CreateInternetService-options-test.xml</ignoredResource>
+                        <ignoredResource>.gitattributes</ignoredResource>
                     </ignoredResources>
                     <failBuildInCaseOfConflict>true</failBuildInCaseOfConflict>
                 </configuration>
diff --git a/providers/hpcloud-objectstorage/src/main/java/org/jclouds/hpcloud/objectstorage/HPCloudObjectStorageAsyncClient.java b/providers/hpcloud-objectstorage/src/main/java/org/jclouds/hpcloud/objectstorage/HPCloudObjectStorageAsyncClient.java
index 49309e6..ae49064 100644
--- a/providers/hpcloud-objectstorage/src/main/java/org/jclouds/hpcloud/objectstorage/HPCloudObjectStorageAsyncClient.java
+++ b/providers/hpcloud-objectstorage/src/main/java/org/jclouds/hpcloud/objectstorage/HPCloudObjectStorageAsyncClient.java
@@ -23,16 +23,11 @@
 import javax.ws.rs.Consumes;
 import javax.ws.rs.DELETE;
 import javax.ws.rs.GET;
-import javax.ws.rs.HEAD;
-import javax.ws.rs.PUT;
 import javax.ws.rs.Path;
 import javax.ws.rs.PathParam;
 import javax.ws.rs.core.MediaType;
 
-import org.jclouds.blobstore.functions.ReturnNullOnContainerNotFound;
 import org.jclouds.hpcloud.objectstorage.extensions.HPCloudCDNAsyncClient;
-import org.jclouds.hpcloud.objectstorage.functions.ParseContainerMetadataFromHeaders;
-import org.jclouds.hpcloud.objectstorage.options.CreateContainerOptions;
 import org.jclouds.openstack.keystone.v2_0.filters.AuthenticateRequest;
 import org.jclouds.openstack.swift.CommonSwiftAsyncClient;
 import org.jclouds.openstack.swift.Storage;
@@ -44,10 +39,8 @@
 import org.jclouds.rest.annotations.ExceptionParser;
 import org.jclouds.rest.annotations.QueryParams;
 import org.jclouds.rest.annotations.RequestFilters;
-import org.jclouds.rest.annotations.ResponseParser;
 import org.jclouds.rest.annotations.SkipEncoding;
 
-import com.google.common.annotations.Beta;
 import com.google.common.base.Optional;
 import com.google.common.util.concurrent.ListenableFuture;
 
@@ -70,24 +63,6 @@
 public interface HPCloudObjectStorageAsyncClient extends CommonSwiftAsyncClient {
 
    /**
-    * @see HPCloudObjectStorageClient#getCDNMetadata(String)
-    */
-   @Beta
-   @HEAD
-   @ResponseParser(ParseContainerMetadataFromHeaders.class)
-   @ExceptionParser(ReturnNullOnContainerNotFound.class)
-   @Path("/{container}")
-   ListenableFuture<ContainerMetadata> getContainerMetadata(@PathParam("container") String container);
-
-   /**
-    * @see HPCloudObjectStorageClient#createContainer
-    */
-   @PUT
-   @Path("/{container}")
-   ListenableFuture<Boolean> createContainer(@PathParam("container") String container,
-            CreateContainerOptions... options);
-
-   /**
     * @see org.jclouds.openstack.swift.CommonSwiftClient#listContainers
     */
    @GET
diff --git a/providers/hpcloud-objectstorage/src/main/java/org/jclouds/hpcloud/objectstorage/HPCloudObjectStorageClient.java b/providers/hpcloud-objectstorage/src/main/java/org/jclouds/hpcloud/objectstorage/HPCloudObjectStorageClient.java
index fc7bbdd..92dc16c 100644
--- a/providers/hpcloud-objectstorage/src/main/java/org/jclouds/hpcloud/objectstorage/HPCloudObjectStorageClient.java
+++ b/providers/hpcloud-objectstorage/src/main/java/org/jclouds/hpcloud/objectstorage/HPCloudObjectStorageClient.java
@@ -22,9 +22,7 @@
 
 import org.jclouds.concurrent.Timeout;
 import org.jclouds.hpcloud.objectstorage.extensions.HPCloudCDNClient;
-import org.jclouds.hpcloud.objectstorage.options.CreateContainerOptions;
 import org.jclouds.openstack.swift.CommonSwiftClient;
-import org.jclouds.openstack.swift.domain.ContainerMetadata;
 import org.jclouds.rest.annotations.Delegate;
 
 import com.google.common.base.Optional;
@@ -46,10 +44,6 @@
 @Timeout(duration = 120, timeUnit = TimeUnit.SECONDS)
 public interface HPCloudObjectStorageClient extends CommonSwiftClient {
 
-   boolean createContainer(String container, CreateContainerOptions... options);
-
-   ContainerMetadata getContainerMetadata(String container);
-
    /**
     * Provides synchronous access to CDN features.
     */
diff --git a/providers/hpcloud-objectstorage/src/main/java/org/jclouds/hpcloud/objectstorage/functions/ParseContainerMetadataFromHeaders.java b/providers/hpcloud-objectstorage/src/main/java/org/jclouds/hpcloud/objectstorage/functions/ParseContainerMetadataFromHeaders.java
deleted file mode 100644
index f9e50c3..0000000
--- a/providers/hpcloud-objectstorage/src/main/java/org/jclouds/hpcloud/objectstorage/functions/ParseContainerMetadataFromHeaders.java
+++ /dev/null
@@ -1,74 +0,0 @@
-/**
- * Licensed to jclouds, Inc. (jclouds) under one or more
- * contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  jclouds licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.jclouds.hpcloud.objectstorage.functions;
-
-import static com.google.common.base.Preconditions.checkArgument;
-
-import java.util.Map;
-import java.util.Map.Entry;
-
-import org.jclouds.http.HttpRequest;
-import org.jclouds.http.HttpResponse;
-import org.jclouds.openstack.swift.domain.ContainerMetadata;
-import org.jclouds.openstack.swift.reference.SwiftHeaders;
-import org.jclouds.rest.InvocationContext;
-import org.jclouds.rest.internal.GeneratedHttpRequest;
-
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.Function;
-import com.google.common.collect.Maps;
-
-/**
- * This parses @{link {@link org.jclouds.openstack.swift.domain.ContainerMetadata} from
- * HTTP headers.
- * 
- * @author Jeremy Daggett
- */
-public class ParseContainerMetadataFromHeaders implements Function<HttpResponse, ContainerMetadata>,
-      InvocationContext<ParseContainerMetadataFromHeaders> {
-   private GeneratedHttpRequest request;
-
-   public ContainerMetadata apply(HttpResponse from) {
-      return ContainerMetadata.builder().name(request.getArgs().get(0).toString())
-            .readACL(from.getFirstHeaderOrNull(SwiftHeaders.CONTAINER_READ))
-            .bytes(Long.valueOf(from.getFirstHeaderOrNull(SwiftHeaders.CONTAINER_BYTES_USED)))
-            .count(Long.valueOf(from.getFirstHeaderOrNull(SwiftHeaders.CONTAINER_OBJECT_COUNT)))
-            .metadata(extractUserMetadata(from)).build();
-   }
-
-   
-   @VisibleForTesting
-   Map<String, String> extractUserMetadata(HttpResponse from) {
-      Map<String, String> metadata = Maps.newHashMap();
-      for (Entry<String, String> header : from.getHeaders().entries()) {
-         if (header.getKey() != null && header.getKey().startsWith(SwiftHeaders.CONTAINER_METADATA_PREFIX))
-            metadata.put((header.getKey().substring(SwiftHeaders.CONTAINER_METADATA_PREFIX.length())).toLowerCase(),
-                  header.getValue());
-      }
-      return metadata;
-   }
-   
-   @Override
-   public ParseContainerMetadataFromHeaders setContext(HttpRequest request) {
-      checkArgument(request instanceof GeneratedHttpRequest, "note this handler requires a GeneratedHttpRequest");
-      this.request = (GeneratedHttpRequest) request;
-      return this;
-   }
-
-}
diff --git a/providers/hpcloud-objectstorage/src/main/java/org/jclouds/hpcloud/objectstorage/options/CreateContainerOptions.java b/providers/hpcloud-objectstorage/src/main/java/org/jclouds/hpcloud/objectstorage/options/CreateContainerOptions.java
deleted file mode 100644
index c995938..0000000
--- a/providers/hpcloud-objectstorage/src/main/java/org/jclouds/hpcloud/objectstorage/options/CreateContainerOptions.java
+++ /dev/null
@@ -1,81 +0,0 @@
-/**
- * Licensed to jclouds, Inc. (jclouds) under one or more
- * contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  jclouds licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.jclouds.hpcloud.objectstorage.options;
-
-import java.util.Map;
-import java.util.Map.Entry;
-
-import org.jclouds.http.options.BaseHttpRequestOptions;
-import org.jclouds.openstack.swift.reference.SwiftHeaders;
-
-/**
- * Contains options supported in the REST API for the Create Container operation.
- * 
- * This specifically enables the Swift ACL for public reads using the 'X-Container-Read'
- * header. This should be refactored into the Swift API.
- * 
- * @author Jeremy Daggett
- */
-public class CreateContainerOptions extends BaseHttpRequestOptions {
-   public static final CreateContainerOptions NONE = new CreateContainerOptions();
-
-   /**
-    * A name-value pair to associate with the container as metadata.
-    */
-   public CreateContainerOptions withMetadata(Map<String, String> metadata) {
-      for (Entry<String, String> entry : metadata.entrySet()) {
-         if (entry.getKey().startsWith(SwiftHeaders.CONTAINER_METADATA_PREFIX)) {
-            this.headers.put(entry.getKey(), entry.getValue());
-      	 } else {
-            this.headers.put(SwiftHeaders.CONTAINER_METADATA_PREFIX + entry.getKey(), 
-            		    entry.getValue());
-   	     }
-      }
-      return this;
-   }
-   
-
-   /**
-    * Indicates whether a container may be accessed publicly
-    */
-   public CreateContainerOptions withPublicAccess() {
-      this.headers.put(SwiftHeaders.CONTAINER_READ, ".r:*,.rlistings");
-      return this;
-   }
-
-   public static class Builder {
-
-      /**
-       * @see org.jclouds.hpcloud.objectstorage.options.CreateContainerOptions#withPublicAccess
-       */
-      public static CreateContainerOptions withPublicAccess() {
-         CreateContainerOptions options = new CreateContainerOptions();
-         return options.withPublicAccess();
-      }
-
-      /**
-       * @see org.jclouds.hpcloud.objectstorage.options.CreateContainerOptions#withMetadata(Multimap<String, String>)
-       */ 
-      public static CreateContainerOptions withMetadata(Map<String, String> metadata) {
-         CreateContainerOptions options = new CreateContainerOptions();
-         return (CreateContainerOptions) options.withMetadata(metadata);
-      }
-	  
-   }
-}
diff --git a/providers/hpcloud-objectstorage/src/test/java/org/jclouds/hpcloud/objectstorage/options/CreateContainerOptionsTest.java b/providers/hpcloud-objectstorage/src/test/java/org/jclouds/hpcloud/objectstorage/options/CreateContainerOptionsTest.java
deleted file mode 100644
index 1238aa3..0000000
--- a/providers/hpcloud-objectstorage/src/test/java/org/jclouds/hpcloud/objectstorage/options/CreateContainerOptionsTest.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/**
- * Licensed to jclouds, Inc. (jclouds) under one or more
- * contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  jclouds licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.jclouds.hpcloud.objectstorage.options;
-
-import static org.testng.Assert.assertEquals;
-
-import org.jclouds.openstack.swift.reference.SwiftHeaders;
-import org.testng.annotations.Test;
-
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableMap;
-
-/**
- * Tests behavior of {@code CreateContainerOptions}
- * 
- * @author Adrian Cole
- */
-@Test(groups = "unit")
-public class CreateContainerOptionsTest {
-
-   public void testPublicAccess() {
-      CreateContainerOptions options = new CreateContainerOptions().withPublicAccess();
-      assertEquals(ImmutableList.of(".r:*,.rlistings"), 
-    		       options.buildRequestHeaders().get("X-Container-Read"));
-   }
-
-   public void testPublicAccessStatic() {
-      CreateContainerOptions options = CreateContainerOptions.Builder.withPublicAccess();
-      assertEquals(ImmutableList.of(".r:*,.rlistings"), 
-    		       options.buildRequestHeaders().get("X-Container-Read"));
-   }
-
-   public void testMetadata() {
-      CreateContainerOptions options = new CreateContainerOptions().withMetadata(ImmutableMap
-               .of("test", "foo"));
-      assertEquals(ImmutableList.of("foo"), options.buildRequestHeaders().get(
-               SwiftHeaders.CONTAINER_METADATA_PREFIX + "test"));
-   }
-
-   public void testMetadataAlreadyPrefixed() {
-      CreateContainerOptions options = new CreateContainerOptions().withMetadata(ImmutableMap
-               .of(SwiftHeaders.CONTAINER_METADATA_PREFIX + "test", "foo"));
-      assertEquals(ImmutableList.of("foo"), options.buildRequestHeaders().get(
-    		  SwiftHeaders.CONTAINER_METADATA_PREFIX + "test"));
-   }
-
-   public void testMetadataStatic() {
-      CreateContainerOptions options = CreateContainerOptions.Builder
-               .withMetadata(ImmutableMap.of("test", "foo"));
-      assertEquals(ImmutableList.of("foo"), options.buildRequestHeaders().get(
-    		  SwiftHeaders.CONTAINER_METADATA_PREFIX + "test"));
-   }
-
-}
diff --git a/scriptbuilder/src/main/resources/functions/.gitattributes b/scriptbuilder/src/main/resources/functions/.gitattributes
new file mode 100644
index 0000000..ba409ff
--- /dev/null
+++ b/scriptbuilder/src/main/resources/functions/.gitattributes
@@ -0,0 +1 @@
+*.sh -crlf
diff --git a/scriptbuilder/src/main/resources/functions/setupPublicCurl.sh b/scriptbuilder/src/main/resources/functions/setupPublicCurl.sh
index 89df345..b299200 100644
--- a/scriptbuilder/src/main/resources/functions/setupPublicCurl.sh
+++ b/scriptbuilder/src/main/resources/functions/setupPublicCurl.sh
@@ -33,7 +33,7 @@
 
 # download locations for many services are at public dns
 function ensure_can_resolve_public_dns() {
-  nslookup yahoo.com > /dev/null || echo nameserver 208.67.222.222 >> /etc/resolv.conf
+  nslookup yahoo.com | grep yahoo.com > /dev/null || echo nameserver 208.67.222.222 >> /etc/resolv.conf
 }
 
 function setupPublicCurl() {
diff --git a/scriptbuilder/src/test/resources/.gitattributes b/scriptbuilder/src/test/resources/.gitattributes
new file mode 100644
index 0000000..ba409ff
--- /dev/null
+++ b/scriptbuilder/src/test/resources/.gitattributes
@@ -0,0 +1 @@
+*.sh -crlf
diff --git a/scriptbuilder/src/test/resources/functions/.gitattributes b/scriptbuilder/src/test/resources/functions/.gitattributes
new file mode 100644
index 0000000..ba409ff
--- /dev/null
+++ b/scriptbuilder/src/test/resources/functions/.gitattributes
@@ -0,0 +1 @@
+*.sh -crlf
diff --git a/scriptbuilder/src/test/resources/test_install_git_scriptbuilder.sh b/scriptbuilder/src/test/resources/test_install_git_scriptbuilder.sh
index d942959..7539de4 100644
--- a/scriptbuilder/src/test/resources/test_install_git_scriptbuilder.sh
+++ b/scriptbuilder/src/test/resources/test_install_git_scriptbuilder.sh
@@ -118,7 +118,7 @@
 
 # download locations for many services are at public dns
 function ensure_can_resolve_public_dns() {
-  nslookup yahoo.com > /dev/null || echo nameserver 208.67.222.222 >> /etc/resolv.conf
+  nslookup yahoo.com | grep yahoo.com > /dev/null || echo nameserver 208.67.222.222 >> /etc/resolv.conf
 }
 
 function setupPublicCurl() {
diff --git a/scriptbuilder/src/test/resources/test_install_jdk_scriptbuilder.sh b/scriptbuilder/src/test/resources/test_install_jdk_scriptbuilder.sh
index 8183a52..b9dae5e 100644
--- a/scriptbuilder/src/test/resources/test_install_jdk_scriptbuilder.sh
+++ b/scriptbuilder/src/test/resources/test_install_jdk_scriptbuilder.sh
@@ -118,7 +118,7 @@
 
 # download locations for many services are at public dns
 function ensure_can_resolve_public_dns() {
-  nslookup yahoo.com > /dev/null || echo nameserver 208.67.222.222 >> /etc/resolv.conf
+  nslookup yahoo.com | grep yahoo.com > /dev/null || echo nameserver 208.67.222.222 >> /etc/resolv.conf
 }
 
 function setupPublicCurl() {