Repository: jclouds-labs
Updated Branches:
  refs/heads/master 6e5082f71 -> 84ebe3d33


Adding Dimension Data Infrastructure API


Project: http://git-wip-us.apache.org/repos/asf/jclouds-labs/repo
Commit: http://git-wip-us.apache.org/repos/asf/jclouds-labs/commit/84ebe3d3
Tree: http://git-wip-us.apache.org/repos/asf/jclouds-labs/tree/84ebe3d3
Diff: http://git-wip-us.apache.org/repos/asf/jclouds-labs/diff/84ebe3d3

Branch: refs/heads/master
Commit: 84ebe3d335ee1e62ce2bdd1f69ecdd2f3d9c3f55
Parents: 6e5082f
Author: Gordon A. Jones <[email protected]>
Authored: Mon Mar 27 14:45:43 2017 +0100
Committer: Ignasi Barrera <[email protected]>
Committed: Mon Mar 27 16:03:42 2017 +0200

----------------------------------------------------------------------
 .../DimensionDataCloudControlApi.java           |   4 +
 .../features/InfrastructureApi.java             | 147 +++++++++++
 .../DatacenterIdListDatacentersFilter.java      |  45 ++++
 .../features/AccountApiMockTest.java            |   5 +-
 .../features/InfrastructureApiLiveTest.java     |  52 ++++
 .../features/InfrastructureApiMockTest.java     | 111 +++++++++
 .../BaseAccountAwareCloudControlMockTest.java   |  52 ++++
 .../BaseDimensionDataCloudControlMockTest.java  |  68 ++++-
 .../options/PaginationOptionsTest.java          |  83 +++++++
 .../src/test/resources/datacenters-page1.json   | 118 +++++++++
 .../src/test/resources/datacenters-page2.json   | 137 ++++++++++
 .../src/test/resources/datacenters.json         | 247 +++++++++++++++++++
 .../test/resources/operatingSystems-page1.json  | 108 ++++++++
 .../test/resources/operatingSystems-page2.json  |  73 ++++++
 .../src/test/resources/operatingSystems.json    | 173 +++++++++++++
 15 files changed, 1419 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/84ebe3d3/dimensiondata/src/main/java/org/jclouds/dimensiondata/cloudcontrol/DimensionDataCloudControlApi.java
----------------------------------------------------------------------
diff --git 
a/dimensiondata/src/main/java/org/jclouds/dimensiondata/cloudcontrol/DimensionDataCloudControlApi.java
 
b/dimensiondata/src/main/java/org/jclouds/dimensiondata/cloudcontrol/DimensionDataCloudControlApi.java
index dc87737..a3b81c8 100644
--- 
a/dimensiondata/src/main/java/org/jclouds/dimensiondata/cloudcontrol/DimensionDataCloudControlApi.java
+++ 
b/dimensiondata/src/main/java/org/jclouds/dimensiondata/cloudcontrol/DimensionDataCloudControlApi.java
@@ -17,6 +17,7 @@
 package org.jclouds.dimensiondata.cloudcontrol;
 
 import org.jclouds.dimensiondata.cloudcontrol.features.AccountApi;
+import org.jclouds.dimensiondata.cloudcontrol.features.InfrastructureApi;
 import org.jclouds.rest.annotations.Delegate;
 
 import java.io.Closeable;
@@ -25,4 +26,7 @@ public interface DimensionDataCloudControlApi extends 
Closeable {
 
    @Delegate
    AccountApi getAccountApi();
+
+   @Delegate
+   InfrastructureApi getInfrastructureApi();
 }

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/84ebe3d3/dimensiondata/src/main/java/org/jclouds/dimensiondata/cloudcontrol/features/InfrastructureApi.java
----------------------------------------------------------------------
diff --git 
a/dimensiondata/src/main/java/org/jclouds/dimensiondata/cloudcontrol/features/InfrastructureApi.java
 
b/dimensiondata/src/main/java/org/jclouds/dimensiondata/cloudcontrol/features/InfrastructureApi.java
new file mode 100644
index 0000000..a5b0d0b
--- /dev/null
+++ 
b/dimensiondata/src/main/java/org/jclouds/dimensiondata/cloudcontrol/features/InfrastructureApi.java
@@ -0,0 +1,147 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.dimensiondata.cloudcontrol.features;
+
+import com.google.common.base.Function;
+import com.google.common.base.Optional;
+import com.google.inject.TypeLiteral;
+import org.jclouds.Fallbacks;
+import org.jclouds.collect.IterableWithMarker;
+import org.jclouds.collect.PagedIterable;
+import org.jclouds.collect.internal.Arg0ToPagedIterable;
+import org.jclouds.dimensiondata.cloudcontrol.DimensionDataCloudControlApi;
+import org.jclouds.dimensiondata.cloudcontrol.domain.Datacenter;
+import org.jclouds.dimensiondata.cloudcontrol.domain.Datacenters;
+import org.jclouds.dimensiondata.cloudcontrol.domain.OperatingSystem;
+import org.jclouds.dimensiondata.cloudcontrol.domain.OperatingSystems;
+import org.jclouds.dimensiondata.cloudcontrol.domain.PaginatedCollection;
+import 
org.jclouds.dimensiondata.cloudcontrol.filters.DatacenterIdListDatacentersFilter;
+import org.jclouds.dimensiondata.cloudcontrol.filters.OrganisationIdFilter;
+import org.jclouds.dimensiondata.cloudcontrol.options.PaginationOptions;
+import org.jclouds.http.filters.BasicAuthentication;
+import org.jclouds.http.functions.ParseJson;
+import org.jclouds.json.Json;
+import org.jclouds.rest.annotations.Fallback;
+import org.jclouds.rest.annotations.RequestFilters;
+import org.jclouds.rest.annotations.ResponseParser;
+import org.jclouds.rest.annotations.Transform;
+
+import javax.inject.Inject;
+import javax.inject.Named;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.MediaType;
+
+@RequestFilters({ BasicAuthentication.class, OrganisationIdFilter.class })
+@Consumes(MediaType.APPLICATION_JSON)
+@Path("/caas/{jclouds.api-version}/infrastructure")
+public interface InfrastructureApi {
+
+   @Named("infrastructure:datacenter")
+   @GET
+   @Path("/datacenter")
+   @ResponseParser(ParseDatacenters.class)
+   @Fallback(Fallbacks.EmptyIterableWithMarkerOnNotFoundOr404.class)
+   PaginatedCollection<Datacenter> listDatacenters(PaginationOptions options);
+
+   @Named("infrastructure:datacenter")
+   @GET
+   @Path("/datacenter")
+   @Transform(ParseDatacenters.ToPagedIterable.class)
+   @ResponseParser(ParseDatacenters.class)
+   @RequestFilters(DatacenterIdListDatacentersFilter.class)
+   @Fallback(Fallbacks.EmptyPagedIterableOnNotFoundOr404.class)
+   PagedIterable<Datacenter> listDatacenters();
+
+   @Named("infrastructure:operatingSystem")
+   @GET
+   @Path("/operatingSystem")
+   @ResponseParser(ParseOperatingSystems.class)
+   @Fallback(Fallbacks.EmptyIterableWithMarkerOnNotFoundOr404.class)
+   PaginatedCollection<OperatingSystem> 
listOperatingSystems(@QueryParam("datacenterId") String datacenterId,
+         PaginationOptions options);
+
+   @Named("infrastructure:operatingSystem")
+   @GET
+   @Path("/operatingSystem")
+   @Transform(ParseOperatingSystems.ToPagedIterable.class)
+   @ResponseParser(ParseOperatingSystems.class)
+   @Fallback(Fallbacks.EmptyPagedIterableOnNotFoundOr404.class)
+   PagedIterable<OperatingSystem> 
listOperatingSystems(@QueryParam("datacenterId") String datacenterId);
+
+   final class ParseDatacenters extends ParseJson<Datacenters> {
+
+      @Inject
+      ParseDatacenters(Json json) {
+         super(json, TypeLiteral.get(Datacenters.class));
+      }
+
+      private static class ToPagedIterable extends 
Arg0ToPagedIterable<Datacenter, ToPagedIterable> {
+
+         private DimensionDataCloudControlApi api;
+
+         @Inject
+         ToPagedIterable(DimensionDataCloudControlApi api) {
+            this.api = api;
+         }
+
+         @Override
+         protected Function<Object, IterableWithMarker<Datacenter>> 
markerToNextForArg0(Optional<Object> arg) {
+            return new Function<Object, IterableWithMarker<Datacenter>>() {
+               @Override
+               public IterableWithMarker<Datacenter> apply(Object input) {
+                  PaginationOptions paginationOptions = 
PaginationOptions.class.cast(input);
+                  return 
api.getInfrastructureApi().listDatacenters(paginationOptions);
+               }
+            };
+         }
+      }
+   }
+
+   final class ParseOperatingSystems extends ParseJson<OperatingSystems> {
+
+      @Inject
+      ParseOperatingSystems(Json json) {
+         super(json, TypeLiteral.get(OperatingSystems.class));
+      }
+
+      private static class ToPagedIterable extends 
Arg0ToPagedIterable<OperatingSystem, ToPagedIterable> {
+
+         private DimensionDataCloudControlApi api;
+
+         @Inject
+         ToPagedIterable(DimensionDataCloudControlApi api) {
+            this.api = api;
+         }
+
+         @Override
+         protected Function<Object, IterableWithMarker<OperatingSystem>> 
markerToNextForArg0(
+               final Optional<Object> arg) {
+            return new Function<Object, IterableWithMarker<OperatingSystem>>() 
{
+               @Override
+               public IterableWithMarker<OperatingSystem> apply(Object input) {
+                  PaginationOptions paginationOptions = 
PaginationOptions.class.cast(input);
+                  return 
api.getInfrastructureApi().listOperatingSystems(arg.get().toString(), 
paginationOptions);
+               }
+            };
+         }
+      }
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/84ebe3d3/dimensiondata/src/main/java/org/jclouds/dimensiondata/cloudcontrol/filters/DatacenterIdListDatacentersFilter.java
----------------------------------------------------------------------
diff --git 
a/dimensiondata/src/main/java/org/jclouds/dimensiondata/cloudcontrol/filters/DatacenterIdListDatacentersFilter.java
 
b/dimensiondata/src/main/java/org/jclouds/dimensiondata/cloudcontrol/filters/DatacenterIdListDatacentersFilter.java
new file mode 100644
index 0000000..ffb7a82
--- /dev/null
+++ 
b/dimensiondata/src/main/java/org/jclouds/dimensiondata/cloudcontrol/filters/DatacenterIdListDatacentersFilter.java
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.dimensiondata.cloudcontrol.filters;
+
+import com.google.common.base.Supplier;
+import org.jclouds.http.HttpException;
+import org.jclouds.http.HttpRequest;
+import org.jclouds.http.HttpRequestFilter;
+import org.jclouds.location.Zone;
+
+import javax.inject.Inject;
+import java.util.Set;
+
+/**
+ * Adds set of Datacenter IDs as set in jclouds.zones JVM property.
+ */
+public class DatacenterIdListDatacentersFilter implements HttpRequestFilter {
+   @Inject
+   @Zone
+   protected Supplier<Set<String>> datacenterIdsSupplier;
+
+   @Override
+   public HttpRequest filter(HttpRequest request) throws HttpException {
+      Set<String> datacenterIds = datacenterIdsSupplier.get();
+      if (datacenterIds != null && !datacenterIds.isEmpty()) {
+         return request.toBuilder().addQueryParam("id", datacenterIds).build();
+      } else {
+         return request;
+      }
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/84ebe3d3/dimensiondata/src/test/java/org/jclouds/dimensiondata/cloudcontrol/features/AccountApiMockTest.java
----------------------------------------------------------------------
diff --git 
a/dimensiondata/src/test/java/org/jclouds/dimensiondata/cloudcontrol/features/AccountApiMockTest.java
 
b/dimensiondata/src/test/java/org/jclouds/dimensiondata/cloudcontrol/features/AccountApiMockTest.java
index 12da0ba..577827b 100644
--- 
a/dimensiondata/src/test/java/org/jclouds/dimensiondata/cloudcontrol/features/AccountApiMockTest.java
+++ 
b/dimensiondata/src/test/java/org/jclouds/dimensiondata/cloudcontrol/features/AccountApiMockTest.java
@@ -16,7 +16,6 @@
  */
 package org.jclouds.dimensiondata.cloudcontrol.features;
 
-import com.squareup.okhttp.mockwebserver.MockResponse;
 import org.jclouds.dimensiondata.cloudcontrol.domain.Account;
 import 
org.jclouds.dimensiondata.cloudcontrol.internal.BaseDimensionDataCloudControlMockTest;
 import org.testng.annotations.Test;
@@ -34,12 +33,12 @@ public class AccountApiMockTest extends 
BaseDimensionDataCloudControlMockTest {
       server.enqueue(jsonResponse("/account.json"));
       Account account = api.getAccountApi().getMyAccount();
       assertNotNull(account);
-      assertSent("GET", "/caas/2.4/user/myUser");
+      assertSent(HttpMethod.GET, "/caas/2.4/user/myUser");
    }
 
    @Test
    public void testGetAccount_404() throws Exception {
-      server.enqueue(new MockResponse().setStatus("HTTP/1.1 404 Not Found"));
+      server.enqueue(response404());
       Account account = api.getAccountApi().getMyAccount();
       assertNull(account);
       assertSent(HttpMethod.GET, "/caas/2.4/user/myUser");

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/84ebe3d3/dimensiondata/src/test/java/org/jclouds/dimensiondata/cloudcontrol/features/InfrastructureApiLiveTest.java
----------------------------------------------------------------------
diff --git 
a/dimensiondata/src/test/java/org/jclouds/dimensiondata/cloudcontrol/features/InfrastructureApiLiveTest.java
 
b/dimensiondata/src/test/java/org/jclouds/dimensiondata/cloudcontrol/features/InfrastructureApiLiveTest.java
new file mode 100644
index 0000000..7e95fc2
--- /dev/null
+++ 
b/dimensiondata/src/test/java/org/jclouds/dimensiondata/cloudcontrol/features/InfrastructureApiLiveTest.java
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.dimensiondata.cloudcontrol.features;
+
+import com.google.common.collect.FluentIterable;
+import org.jclouds.dimensiondata.cloudcontrol.domain.Datacenter;
+import org.jclouds.dimensiondata.cloudcontrol.domain.OperatingSystem;
+import 
org.jclouds.dimensiondata.cloudcontrol.internal.BaseDimensionDataCloudControlApiLiveTest;
+import org.testng.annotations.Test;
+
+import static org.testng.Assert.assertNotNull;
+
+@Test(groups = "live", testName = "InfrastructureApiLiveTest", singleThreaded 
= true)
+public class InfrastructureApiLiveTest extends 
BaseDimensionDataCloudControlApiLiveTest {
+
+   @Test
+   public void testListDatacenters() {
+      FluentIterable<Datacenter> datacenters = 
api().listDatacenters().concat();
+      assertNotNull(datacenters);
+      for (Datacenter datacenter : datacenters) {
+         assertNotNull(datacenter);
+      }
+   }
+
+   @Test
+   public void testListOperatingSystems() {
+      FluentIterable<OperatingSystem> operatingSystems = 
api().listOperatingSystems("NA9").concat();
+      assertNotNull(operatingSystems);
+      for (OperatingSystem operatingSystem : operatingSystems) {
+         assertNotNull(operatingSystem);
+      }
+   }
+
+   private InfrastructureApi api() {
+      return api.getInfrastructureApi();
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/84ebe3d3/dimensiondata/src/test/java/org/jclouds/dimensiondata/cloudcontrol/features/InfrastructureApiMockTest.java
----------------------------------------------------------------------
diff --git 
a/dimensiondata/src/test/java/org/jclouds/dimensiondata/cloudcontrol/features/InfrastructureApiMockTest.java
 
b/dimensiondata/src/test/java/org/jclouds/dimensiondata/cloudcontrol/features/InfrastructureApiMockTest.java
new file mode 100644
index 0000000..5ef6048
--- /dev/null
+++ 
b/dimensiondata/src/test/java/org/jclouds/dimensiondata/cloudcontrol/features/InfrastructureApiMockTest.java
@@ -0,0 +1,111 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.dimensiondata.cloudcontrol.features;
+
+import org.jclouds.dimensiondata.cloudcontrol.domain.Datacenter;
+import org.jclouds.dimensiondata.cloudcontrol.domain.OperatingSystem;
+import 
org.jclouds.dimensiondata.cloudcontrol.internal.BaseAccountAwareCloudControlMockTest;
+import org.jclouds.http.Uris;
+import org.jclouds.location.suppliers.ZoneIdsSupplier;
+import org.testng.annotations.Test;
+
+import javax.ws.rs.HttpMethod;
+import java.util.Set;
+
+import static com.google.common.collect.Iterables.size;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+
+/**
+ * Mock tests for the {@link InfrastructureApi} class.
+ */
+@Test(groups = "unit", testName = "InfrastructureApiMockTest", singleThreaded 
= true)
+public class InfrastructureApiMockTest extends 
BaseAccountAwareCloudControlMockTest {
+
+   public void testListDatacenters() throws Exception {
+      server.enqueue(jsonResponse("/datacenters.json"));
+      Iterable<Datacenter> datacenters = 
api.getInfrastructureApi().listDatacenters().concat();
+
+      assertEquals(size(datacenters), 2); // Force the PagedIterable to advance
+      assertEquals(server.getRequestCount(), 2);
+
+      assertSent(HttpMethod.GET, 
expectedListDatacentersUriBuilder().toString());
+   }
+
+   public void testListDatacentersWithPagination() throws Exception {
+      server.enqueue(jsonResponse("/datacenters-page1.json"));
+      server.enqueue(jsonResponse("/datacenters-page2.json"));
+      Iterable<Datacenter> datacenters = 
api.getInfrastructureApi().listDatacenters().concat();
+
+      consumeIterableAndAssertAdditionalPagesRequested(datacenters, 2, 1);
+
+      assertSent(HttpMethod.GET, 
expectedListDatacentersUriBuilder().toString());
+      assertSent(HttpMethod.GET, 
addPageNumberToUriBuilder(expectedListDatacentersUriBuilder(), 2).toString());
+   }
+
+   public void testListDatacenters404() throws Exception {
+      server.enqueue(response404());
+      
assertTrue(api.getInfrastructureApi().listDatacenters().concat().isEmpty());
+      assertSent(HttpMethod.GET, 
expectedListDatacentersUriBuilder().toString());
+   }
+
+   private Uris.UriBuilder expectedListDatacentersUriBuilder() {
+      Uris.UriBuilder uriBuilder = Uris
+            
.uriBuilder("/caas/2.4/6ac1e746-b1ea-4da5-a24e-caf1a978789d/infrastructure/datacenter");
+      Set<String> zones = 
ctx.utils().injector().getInstance(ZoneIdsSupplier.class).get();
+      for (String zone : zones) {
+         uriBuilder.addQuery("id", zone);
+      }
+      return uriBuilder;
+   }
+
+   public void testListOperatingSystems() throws Exception {
+      server.enqueue(jsonResponse("/operatingSystems.json"));
+      Iterable<OperatingSystem> operatingSystems = 
api.getInfrastructureApi().listOperatingSystems("NA9").concat();
+
+      assertEquals(size(operatingSystems), 33);
+      assertEquals(server.getRequestCount(), 2);
+
+      assertSent(HttpMethod.GET, 
expectedListOperatingSystemsUriBuilder().toString());
+   }
+
+   public void testListOperatingSystemsWithPagination() throws Exception {
+      server.enqueue(jsonResponse("/operatingSystems-page1.json"));
+      server.enqueue(jsonResponse("/operatingSystems-page2.json"));
+      Iterable<OperatingSystem> operatingSystems = 
api.getInfrastructureApi().listOperatingSystems("NA9").concat();
+
+      consumeIterableAndAssertAdditionalPagesRequested(operatingSystems, 33, 
1);
+
+      assertSent(HttpMethod.GET, 
expectedListOperatingSystemsUriBuilder().toString());
+      assertSent(HttpMethod.GET, 
addPageNumberToUriBuilder(expectedListOperatingSystemsUriBuilder(), 
2).toString());
+
+   }
+
+   public void testListOperatingSystems404() throws Exception {
+      server.enqueue(response404());
+      
assertTrue(api.getInfrastructureApi().listOperatingSystems("NA9").concat().isEmpty());
+      assertSent(HttpMethod.GET, 
expectedListOperatingSystemsUriBuilder().toString());
+   }
+
+   private Uris.UriBuilder expectedListOperatingSystemsUriBuilder() {
+      Uris.UriBuilder uriBuilder = Uris
+            
.uriBuilder("/caas/2.4/6ac1e746-b1ea-4da5-a24e-caf1a978789d/infrastructure/operatingSystem");
+      uriBuilder.addQuery("datacenterId", "NA9");
+      return uriBuilder;
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/84ebe3d3/dimensiondata/src/test/java/org/jclouds/dimensiondata/cloudcontrol/internal/BaseAccountAwareCloudControlMockTest.java
----------------------------------------------------------------------
diff --git 
a/dimensiondata/src/test/java/org/jclouds/dimensiondata/cloudcontrol/internal/BaseAccountAwareCloudControlMockTest.java
 
b/dimensiondata/src/test/java/org/jclouds/dimensiondata/cloudcontrol/internal/BaseAccountAwareCloudControlMockTest.java
new file mode 100644
index 0000000..ef6891d
--- /dev/null
+++ 
b/dimensiondata/src/test/java/org/jclouds/dimensiondata/cloudcontrol/internal/BaseAccountAwareCloudControlMockTest.java
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.dimensiondata.cloudcontrol.internal;
+
+import com.squareup.okhttp.mockwebserver.RecordedRequest;
+import org.testng.annotations.BeforeMethod;
+
+import javax.ws.rs.HttpMethod;
+
+/**
+ * Base class for Dimension Data Cloud Control mock tests for API calls that 
include account information.
+ * <p>
+ * The first time an account-aware method is called in a testcase the 'myUser' 
endpoint should be called to look up
+ * the account for the user. This class checks that this call happened before 
the first call to other endpoints.
+ */
+public class BaseAccountAwareCloudControlMockTest extends 
BaseDimensionDataCloudControlMockTest {
+
+   private boolean accountRetrieved;
+
+   @Override
+   protected void applyAdditionalServerConfig() {
+      server.enqueue(jsonResponse("/account.json"));
+   }
+
+   @BeforeMethod
+   public void reset() {
+      accountRetrieved = false;
+   }
+
+   @Override
+   protected RecordedRequest assertSent(String method, String path) throws 
InterruptedException {
+      if (!accountRetrieved) {
+         super.assertSent(HttpMethod.GET, "/caas/2.4/user/myUser");
+         accountRetrieved = true;
+      }
+      return super.assertSent(method, path);
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/84ebe3d3/dimensiondata/src/test/java/org/jclouds/dimensiondata/cloudcontrol/internal/BaseDimensionDataCloudControlMockTest.java
----------------------------------------------------------------------
diff --git 
a/dimensiondata/src/test/java/org/jclouds/dimensiondata/cloudcontrol/internal/BaseDimensionDataCloudControlMockTest.java
 
b/dimensiondata/src/test/java/org/jclouds/dimensiondata/cloudcontrol/internal/BaseDimensionDataCloudControlMockTest.java
index 0ea17cf..1c0d0d2 100644
--- 
a/dimensiondata/src/test/java/org/jclouds/dimensiondata/cloudcontrol/internal/BaseDimensionDataCloudControlMockTest.java
+++ 
b/dimensiondata/src/test/java/org/jclouds/dimensiondata/cloudcontrol/internal/BaseDimensionDataCloudControlMockTest.java
@@ -29,8 +29,12 @@ import org.jclouds.ContextBuilder;
 import org.jclouds.concurrent.config.ExecutorServiceModule;
 import org.jclouds.dimensiondata.cloudcontrol.DimensionDataCloudControlApi;
 import 
org.jclouds.dimensiondata.cloudcontrol.DimensionDataCloudControlProviderMetadata;
+import org.jclouds.http.Uris;
 import org.jclouds.json.Json;
 import org.jclouds.rest.ApiContext;
+import org.testng.IHookCallBack;
+import org.testng.IHookable;
+import org.testng.ITestResult;
 import org.testng.annotations.AfterMethod;
 import org.testng.annotations.BeforeMethod;
 
@@ -40,13 +44,16 @@ import java.io.IOException;
 import java.util.Properties;
 import java.util.Set;
 
+import static com.google.common.collect.Iterables.size;
 import static 
com.google.common.util.concurrent.MoreExecutors.sameThreadExecutor;
 import static org.assertj.core.api.Assertions.assertThat;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.fail;
 
 /**
  * Base class for all DimensionDataCloudController mock tests.
  */
-public class BaseDimensionDataCloudControlMockTest {
+public class BaseDimensionDataCloudControlMockTest implements IHookable {
 
    private static final String DEFAULT_ENDPOINT = new 
DimensionDataCloudControlProviderMetadata().getEndpoint();
 
@@ -56,6 +63,7 @@ public class BaseDimensionDataCloudControlMockTest {
    protected DimensionDataCloudControlApi api;
    protected ApiContext<DimensionDataCloudControlApi> ctx;
    private Json json;
+   private int assertedRequestCount;
 
    // So that we can ignore formatting.
    private final JsonParser parser = new JsonParser();
@@ -68,6 +76,38 @@ public class BaseDimensionDataCloudControlMockTest {
             .endpoint(url("")).modules(modules).overrides(overrides()).build();
       json = ctx.utils().injector().getInstance(Json.class);
       api = ctx.getApi();
+      applyAdditionalServerConfig();
+      assertedRequestCount = 0;
+   }
+
+   /**
+    * Applies any additional configuration required by test classes to the 
mock web server.
+    */
+   protected void applyAdditionalServerConfig() {
+   }
+
+   @Override
+   public void run(IHookCallBack callBack, ITestResult testResult) {
+      callBack.runTestMethod(testResult);
+      ensureAllRequestsWereAsserted();
+   }
+
+   private void ensureAllRequestsWereAsserted() {
+      int unAssertedRequestCount = server.getRequestCount() - 
assertedRequestCount;
+      if (unAssertedRequestCount > 0) {
+         StringBuilder messageBuilder = new StringBuilder(
+               String.format("There were %s un-asserted requests: ", 
unAssertedRequestCount));
+         while (unAssertedRequestCount > 0) {
+            try {
+               
messageBuilder.append('\n').append(server.takeRequest().toString());
+            } catch (InterruptedException e) {
+               messageBuilder.append('\n').append("Error obtaining request 
from mock web server: ")
+                     .append(e.toString());
+            }
+            unAssertedRequestCount--;
+         }
+         fail(messageBuilder.toString());
+      }
    }
 
    @AfterMethod(alwaysRun = true)
@@ -108,6 +148,10 @@ public class BaseDimensionDataCloudControlMockTest {
             .setBody("content: 
[{\"operation\":\"OPERATION\",\"responseCode\":\"RESOURCE_NOT_FOUND\"}]");
    }
 
+   protected MockResponse response404() {
+      return new MockResponse().setStatus("HTTP/1.1 404 Not Found");
+   }
+
    /**
     * Mocked OK 200 Response
     *
@@ -128,6 +172,7 @@ public class BaseDimensionDataCloudControlMockTest {
 
    protected RecordedRequest assertSent(String method, String path) throws 
InterruptedException {
       RecordedRequest request = server.takeRequest();
+      assertedRequestCount++;
       assertThat(request.getMethod()).isEqualTo(method);
       assertThat(request.getPath()).isEqualTo(path);
       
assertThat(request.getHeader(HttpHeaders.ACCEPT)).isEqualTo(MediaType.APPLICATION_JSON);
@@ -138,4 +183,25 @@ public class BaseDimensionDataCloudControlMockTest {
    protected void assertBodyContains(RecordedRequest recordedRequest, String 
expectedText) {
       assertThat(recordedRequest.getUtf8Body()).contains(expectedText);
    }
+
+   /**
+    * Consumes the supplied iterable, checking that it contained the expected 
number of items, and that the expected
+    * number of additional page requests were made in doing so.
+    *
+    * @param iterable                         the iterable to be consumed.
+    * @param expectedSize                     the number of items expected in 
the iterable.
+    * @param expectedAdditionalPagesRequested the number of additional page 
requests that should be made.
+    * @param <T>                              the type of item contained in 
the iterable.
+    */
+   protected <T> void 
consumeIterableAndAssertAdditionalPagesRequested(Iterable<T> iterable, int 
expectedSize,
+         int expectedAdditionalPagesRequested) {
+      int initialRequestCount = server.getRequestCount();
+      assertEquals(size(iterable), expectedSize);
+      assertEquals(server.getRequestCount() - initialRequestCount, 
expectedAdditionalPagesRequested);
+   }
+
+   protected Uris.UriBuilder addPageNumberToUriBuilder(Uris.UriBuilder 
uriBuilder, int pageNumber) {
+      uriBuilder.addQuery("pageNumber", Integer.toString(pageNumber));
+      return uriBuilder;
+   }
 }

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/84ebe3d3/dimensiondata/src/test/java/org/jclouds/dimensiondata/cloudcontrol/options/PaginationOptionsTest.java
----------------------------------------------------------------------
diff --git 
a/dimensiondata/src/test/java/org/jclouds/dimensiondata/cloudcontrol/options/PaginationOptionsTest.java
 
b/dimensiondata/src/test/java/org/jclouds/dimensiondata/cloudcontrol/options/PaginationOptionsTest.java
new file mode 100644
index 0000000..8c0654d
--- /dev/null
+++ 
b/dimensiondata/src/test/java/org/jclouds/dimensiondata/cloudcontrol/options/PaginationOptionsTest.java
@@ -0,0 +1,83 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.dimensiondata.cloudcontrol.options;
+
+import com.google.common.collect.Multimap;
+import org.testng.annotations.Test;
+
+import java.util.Collection;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+
+@Test(groups = "unit", testName = "PaginationOptionsTest")
+public class PaginationOptionsTest {
+
+   @Test()
+   public void orderBy() {
+      PaginationOptions paginationOptions = new PaginationOptions();
+      paginationOptions.orderBy("someField");
+      assertQueryParameter(paginationOptions, "orderBy", "someField");
+   }
+
+   @Test(expectedExceptions = NullPointerException.class)
+   public void orderByNullSupplied() {
+      PaginationOptions paginationOptions = new PaginationOptions();
+      paginationOptions.orderBy(null);
+   }
+
+   @Test()
+   public void pageNumber() {
+      PaginationOptions paginationOptions = new PaginationOptions();
+      paginationOptions.pageNumber(2);
+      assertQueryParameter(paginationOptions, "pageNumber", "2");
+   }
+
+   @Test(expectedExceptions = IllegalStateException.class)
+   public void pageSizeTooSmall() {
+      PaginationOptions paginationOptions = new PaginationOptions();
+      paginationOptions.pageSize(-1);
+   }
+
+   @Test()
+   public void pageSizeMinimum() {
+      PaginationOptions paginationOptions = new PaginationOptions();
+      paginationOptions.pageSize(0);
+      assertQueryParameter(paginationOptions, "pageSize", "0");
+   }
+
+   @Test()
+   public void pageSizeMaximum() {
+      PaginationOptions paginationOptions = new PaginationOptions();
+      paginationOptions.pageSize(10000);
+      assertQueryParameter(paginationOptions, "pageSize", "10000");
+   }
+
+   @Test(expectedExceptions = IllegalStateException.class)
+   public void pageSizeTooBig() {
+      PaginationOptions paginationOptions = new PaginationOptions();
+      paginationOptions.pageSize(10001);
+   }
+
+   private void assertQueryParameter(PaginationOptions paginationOptions, 
String paramaterName, String expectedValue) {
+      Multimap queryParameters = paginationOptions.buildQueryParameters();
+      assertTrue(queryParameters.containsKey(paramaterName));
+      Collection<String> values = queryParameters.get(paramaterName);
+      assertEquals(values.size(), 1);
+      assertEquals(values.iterator().next(), expectedValue);
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/84ebe3d3/dimensiondata/src/test/resources/datacenters-page1.json
----------------------------------------------------------------------
diff --git a/dimensiondata/src/test/resources/datacenters-page1.json 
b/dimensiondata/src/test/resources/datacenters-page1.json
new file mode 100644
index 0000000..e4a31b7
--- /dev/null
+++ b/dimensiondata/src/test/resources/datacenters-page1.json
@@ -0,0 +1,118 @@
+{
+  "datacenter": [
+    {
+      "displayName": "US - West",
+      "city": "Santa Clara",
+      "state": "California",
+      "country": "US",
+      "vpnUrl": "https://na3.cloud-vpn.net";,
+      "ftpsHost": "ftps-na.cloud-vpn.net",
+      "networking": {
+        "property": [
+          {
+            "name": "MAX_SERVER_TO_VIP_CONNECTIONS",
+            "value": "20"
+          }
+        ],
+        "type": "1",
+        "maintenanceStatus": "NORMAL"
+      },
+      "hypervisor": {
+        "diskSpeed": [
+          {
+            "displayName": "Standard",
+            "abbreviation": "STD",
+            "description": "Standard Disk Speed",
+            "id": "STANDARD",
+            "available": true,
+            "default": true
+          },
+          {
+            "displayName": "High Performance",
+            "abbreviation": "HPF",
+            "description": "Faster than Standard. Uses 15000 RPM disk with 
Fast Cache.",
+            "id": "HIGHPERFORMANCE",
+            "available": true,
+            "default": false
+          },
+          {
+            "displayName": "Economy",
+            "abbreviation": "ECN",
+            "description": "Slower than Standard. Uses 7200 RPM disk without 
Fast Cache.",
+            "id": "ECONOMY",
+            "available": true,
+            "default": false
+          }
+        ],
+        "cpuSpeed": [
+          {
+            "displayName": "Standard",
+            "description": "Standard CPU Speed",
+            "id": "STANDARD",
+            "available": true,
+            "default": true
+          }
+        ],
+        "property": [
+          {
+            "name": "MIN_DISK_SIZE_GB",
+            "value": "10"
+          },
+          {
+            "name": "MAX_DISK_SIZE_GB",
+            "value": "1000"
+          },
+          {
+            "name": "MAX_TOTAL_ADDITIONAL_STORAGE_GB",
+            "value": "10000"
+          },
+          {
+            "name": "MAX_TOTAL_IMAGE_STORAGE_GB",
+            "value": "2600"
+          },
+          {
+            "name": "MAX_CPU_COUNT",
+            "value": "16"
+          },
+          {
+            "name": "MIN_MEMORY_GB",
+            "value": "1"
+          },
+          {
+            "name": "MAX_MEMORY_GB",
+            "value": "128"
+          },
+          {
+            "name": "VMWARE_HARDWARE_VERSION",
+            "value": "vmx-10"
+          },
+          {
+            "name": "VLAN_SECURITY_GROUPS_ENABLED",
+            "value": "false"
+          }
+        ],
+        "type": "VMWARE",
+        "maintenanceStatus": "NORMAL"
+      },
+      "backup": {
+        "property": [],
+        "type": "COMMVAULT",
+        "maintenanceStatus": "NORMAL"
+      },
+      "consoleAccess": {
+        "property": [],
+        "maintenanceStatus": "NORMAL"
+      },
+      "monitoring": {
+        "property": [],
+        "maintenanceStatus": "NORMAL"
+      },
+      "id": "NA3",
+      "type": "MCP 1.0"
+    }
+  ],
+  "pageNumber": 1,
+  "pageCount": 1,
+  "totalCount": 2,
+  "pageSize": 1
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/84ebe3d3/dimensiondata/src/test/resources/datacenters-page2.json
----------------------------------------------------------------------
diff --git a/dimensiondata/src/test/resources/datacenters-page2.json 
b/dimensiondata/src/test/resources/datacenters-page2.json
new file mode 100644
index 0000000..3820fc6
--- /dev/null
+++ b/dimensiondata/src/test/resources/datacenters-page2.json
@@ -0,0 +1,137 @@
+{
+  "datacenter": [
+    {
+      "displayName": "US - East 3 - MCP 2.0",
+      "city": "Ashburn",
+      "state": "Virginia",
+      "country": "US",
+      "vpnUrl": "https://na9.cloud-vpn.net";,
+      "ftpsHost": "ftps-na.cloud-vpn.net",
+      "networking": {
+        "property": [
+          {
+            "name": "MAX_NODE_CONNECTION_LIMIT",
+            "value": "100000"
+          },
+          {
+            "name": "MAX_NODE_CONNECTION_RATE_LIMIT",
+            "value": "4000"
+          },
+          {
+            "name": "MAX_VIRTUAL_LISTENER_CONNECTION_LIMIT",
+            "value": "100000"
+          },
+          {
+            "name": "MAX_VIRTUAL_LISTENER_CONNECTION_RATE_LIMIT",
+            "value": "4000"
+          }
+        ],
+        "type": "2",
+        "maintenanceStatus": "NORMAL"
+      },
+      "hypervisor": {
+        "diskSpeed": [
+          {
+            "displayName": "Standard",
+            "abbreviation": "STD",
+            "description": "Standard Disk Speed",
+            "id": "STANDARD",
+            "available": true,
+            "default": true
+          },
+          {
+            "displayName": "High Performance",
+            "abbreviation": "HPF",
+            "description": "Faster than Standard. Uses 15000 RPM disk with 
Fast Cache.",
+            "id": "HIGHPERFORMANCE",
+            "available": true,
+            "default": false
+          },
+          {
+            "displayName": "Economy",
+            "abbreviation": "ECN",
+            "description": "Slower than Standard. Uses 7200 RPM disk without 
Fast Cache.",
+            "id": "ECONOMY",
+            "available": true,
+            "default": false
+          }
+        ],
+        "cpuSpeed": [
+          {
+            "displayName": "Standard",
+            "description": "Standard CPU Speed",
+            "id": "STANDARD",
+            "available": true,
+            "default": true
+          },
+          {
+            "displayName": "High Performance",
+            "description": "Faster and more consistent than Standard. Suitable 
for applications that are more CPU intensive.",
+            "id": "HIGHPERFORMANCE",
+            "available": true,
+            "default": false
+          }
+        ],
+        "property": [
+          {
+            "name": "MIN_DISK_SIZE_GB",
+            "value": "10"
+          },
+          {
+            "name": "MAX_DISK_SIZE_GB",
+            "value": "1000"
+          },
+          {
+            "name": "MAX_TOTAL_ADDITIONAL_STORAGE_GB",
+            "value": "14000"
+          },
+          {
+            "name": "MAX_TOTAL_IMAGE_STORAGE_GB",
+            "value": "2600"
+          },
+          {
+            "name": "MAX_CPU_COUNT",
+            "value": "32"
+          },
+          {
+            "name": "MIN_MEMORY_GB",
+            "value": "1"
+          },
+          {
+            "name": "MAX_MEMORY_GB",
+            "value": "256"
+          },
+          {
+            "name": "VMWARE_HARDWARE_VERSION",
+            "value": "vmx-10"
+          },
+          {
+            "name": "VLAN_SECURITY_GROUPS_ENABLED",
+            "value": "false"
+          }
+        ],
+        "type": "VMWARE",
+        "maintenanceStatus": "NORMAL"
+      },
+      "backup": {
+        "property": [],
+        "type": "COMMVAULT",
+        "maintenanceStatus": "NORMAL"
+      },
+      "consoleAccess": {
+        "property": [],
+        "maintenanceStatus": "NORMAL"
+      },
+      "monitoring": {
+        "property": [],
+        "maintenanceStatus": "NORMAL"
+      },
+      "id": "NA9",
+      "type": "MCP 2.0"
+    }
+  ],
+  "pageNumber": 2,
+  "pageCount": 1,
+  "totalCount": 2,
+  "pageSize": 1
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/84ebe3d3/dimensiondata/src/test/resources/datacenters.json
----------------------------------------------------------------------
diff --git a/dimensiondata/src/test/resources/datacenters.json 
b/dimensiondata/src/test/resources/datacenters.json
new file mode 100644
index 0000000..776a1c6
--- /dev/null
+++ b/dimensiondata/src/test/resources/datacenters.json
@@ -0,0 +1,247 @@
+{
+  "datacenter": [
+    {
+      "displayName": "US - West",
+      "city": "Santa Clara",
+      "state": "California",
+      "country": "US",
+      "vpnUrl": "https://na3.cloud-vpn.net";,
+      "ftpsHost": "ftps-na.cloud-vpn.net",
+      "networking": {
+        "property": [
+          {
+            "name": "MAX_SERVER_TO_VIP_CONNECTIONS",
+            "value": "20"
+          }
+        ],
+        "type": "1",
+        "maintenanceStatus": "NORMAL"
+      },
+      "hypervisor": {
+        "diskSpeed": [
+          {
+            "displayName": "Standard",
+            "abbreviation": "STD",
+            "description": "Standard Disk Speed",
+            "id": "STANDARD",
+            "available": true,
+            "default": true
+          },
+          {
+            "displayName": "High Performance",
+            "abbreviation": "HPF",
+            "description": "Faster than Standard. Uses 15000 RPM disk with 
Fast Cache.",
+            "id": "HIGHPERFORMANCE",
+            "available": true,
+            "default": false
+          },
+          {
+            "displayName": "Economy",
+            "abbreviation": "ECN",
+            "description": "Slower than Standard. Uses 7200 RPM disk without 
Fast Cache.",
+            "id": "ECONOMY",
+            "available": true,
+            "default": false
+          }
+        ],
+        "cpuSpeed": [
+          {
+            "displayName": "Standard",
+            "description": "Standard CPU Speed",
+            "id": "STANDARD",
+            "available": true,
+            "default": true
+          }
+        ],
+        "property": [
+          {
+            "name": "MIN_DISK_SIZE_GB",
+            "value": "10"
+          },
+          {
+            "name": "MAX_DISK_SIZE_GB",
+            "value": "1000"
+          },
+          {
+            "name": "MAX_TOTAL_ADDITIONAL_STORAGE_GB",
+            "value": "10000"
+          },
+          {
+            "name": "MAX_TOTAL_IMAGE_STORAGE_GB",
+            "value": "2600"
+          },
+          {
+            "name": "MAX_CPU_COUNT",
+            "value": "16"
+          },
+          {
+            "name": "MIN_MEMORY_GB",
+            "value": "1"
+          },
+          {
+            "name": "MAX_MEMORY_GB",
+            "value": "128"
+          },
+          {
+            "name": "VMWARE_HARDWARE_VERSION",
+            "value": "vmx-10"
+          },
+          {
+            "name": "VLAN_SECURITY_GROUPS_ENABLED",
+            "value": "false"
+          }
+        ],
+        "type": "VMWARE",
+        "maintenanceStatus": "NORMAL"
+      },
+      "backup": {
+        "property": [],
+        "type": "COMMVAULT",
+        "maintenanceStatus": "NORMAL"
+      },
+      "consoleAccess": {
+        "property": [],
+        "maintenanceStatus": "NORMAL"
+      },
+      "monitoring": {
+        "property": [],
+        "maintenanceStatus": "NORMAL"
+      },
+      "id": "NA3",
+      "type": "MCP 1.0"
+    },
+    {
+      "displayName": "US - East 3 - MCP 2.0",
+      "city": "Ashburn",
+      "state": "Virginia",
+      "country": "US",
+      "vpnUrl": "https://na9.cloud-vpn.net";,
+      "ftpsHost": "ftps-na.cloud-vpn.net",
+      "networking": {
+        "property": [
+          {
+            "name": "MAX_NODE_CONNECTION_LIMIT",
+            "value": "100000"
+          },
+          {
+            "name": "MAX_NODE_CONNECTION_RATE_LIMIT",
+            "value": "4000"
+          },
+          {
+            "name": "MAX_VIRTUAL_LISTENER_CONNECTION_LIMIT",
+            "value": "100000"
+          },
+          {
+            "name": "MAX_VIRTUAL_LISTENER_CONNECTION_RATE_LIMIT",
+            "value": "4000"
+          }
+        ],
+        "type": "2",
+        "maintenanceStatus": "NORMAL"
+      },
+      "hypervisor": {
+        "diskSpeed": [
+          {
+            "displayName": "Standard",
+            "abbreviation": "STD",
+            "description": "Standard Disk Speed",
+            "id": "STANDARD",
+            "available": true,
+            "default": true
+          },
+          {
+            "displayName": "High Performance",
+            "abbreviation": "HPF",
+            "description": "Faster than Standard. Uses 15000 RPM disk with 
Fast Cache.",
+            "id": "HIGHPERFORMANCE",
+            "available": true,
+            "default": false
+          },
+          {
+            "displayName": "Economy",
+            "abbreviation": "ECN",
+            "description": "Slower than Standard. Uses 7200 RPM disk without 
Fast Cache.",
+            "id": "ECONOMY",
+            "available": true,
+            "default": false
+          }
+        ],
+        "cpuSpeed": [
+          {
+            "displayName": "Standard",
+            "description": "Standard CPU Speed",
+            "id": "STANDARD",
+            "available": true,
+            "default": true
+          },
+          {
+            "displayName": "High Performance",
+            "description": "Faster and more consistent than Standard. Suitable 
for applications that are more CPU intensive.",
+            "id": "HIGHPERFORMANCE",
+            "available": true,
+            "default": false
+          }
+        ],
+        "property": [
+          {
+            "name": "MIN_DISK_SIZE_GB",
+            "value": "10"
+          },
+          {
+            "name": "MAX_DISK_SIZE_GB",
+            "value": "1000"
+          },
+          {
+            "name": "MAX_TOTAL_ADDITIONAL_STORAGE_GB",
+            "value": "14000"
+          },
+          {
+            "name": "MAX_TOTAL_IMAGE_STORAGE_GB",
+            "value": "2600"
+          },
+          {
+            "name": "MAX_CPU_COUNT",
+            "value": "32"
+          },
+          {
+            "name": "MIN_MEMORY_GB",
+            "value": "1"
+          },
+          {
+            "name": "MAX_MEMORY_GB",
+            "value": "256"
+          },
+          {
+            "name": "VMWARE_HARDWARE_VERSION",
+            "value": "vmx-10"
+          },
+          {
+            "name": "VLAN_SECURITY_GROUPS_ENABLED",
+            "value": "false"
+          }
+        ],
+        "type": "VMWARE",
+        "maintenanceStatus": "NORMAL"
+      },
+      "backup": {
+        "property": [],
+        "type": "COMMVAULT",
+        "maintenanceStatus": "NORMAL"
+      },
+      "consoleAccess": {
+        "property": [],
+        "maintenanceStatus": "NORMAL"
+      },
+      "monitoring": {
+        "property": [],
+        "maintenanceStatus": "NORMAL"
+      },
+      "id": "NA9",
+      "type": "MCP 2.0"
+    }
+  ],
+  "pageNumber": 1,
+  "pageCount": 2,
+  "totalCount": 2,
+  "pageSize": 250
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/84ebe3d3/dimensiondata/src/test/resources/operatingSystems-page1.json
----------------------------------------------------------------------
diff --git a/dimensiondata/src/test/resources/operatingSystems-page1.json 
b/dimensiondata/src/test/resources/operatingSystems-page1.json
new file mode 100644
index 0000000..5b32a7b
--- /dev/null
+++ b/dimensiondata/src/test/resources/operatingSystems-page1.json
@@ -0,0 +1,108 @@
+{
+  "operatingSystem": [
+    {
+      "id": "CENTOS532",
+      "displayName": "CENTOS5/32",
+      "family": "UNIX"
+    },
+    {
+      "id": "CENTOS564",
+      "displayName": "CENTOS5/64",
+      "family": "UNIX"
+    },
+    {
+      "id": "CENTOS632",
+      "displayName": "CENTOS6/32",
+      "family": "UNIX"
+    },
+    {
+      "id": "CENTOS664",
+      "displayName": "CENTOS6/64",
+      "family": "UNIX"
+    },
+    {
+      "id": "CENTOS764",
+      "displayName": "CENTOS7/64",
+      "family": "UNIX"
+    },
+    {
+      "id": "REDHAT432",
+      "displayName": "REDHAT4/32",
+      "family": "UNIX"
+    },
+    {
+      "id": "REDHAT464",
+      "displayName": "REDHAT4/64",
+      "family": "UNIX"
+    },
+    {
+      "id": "REDHAT532",
+      "displayName": "REDHAT5/32",
+      "family": "UNIX"
+    },
+    {
+      "id": "REDHAT564",
+      "displayName": "REDHAT5/64",
+      "family": "UNIX"
+    },
+    {
+      "id": "REDHAT632",
+      "displayName": "REDHAT6/32",
+      "family": "UNIX"
+    },
+    {
+      "id": "REDHAT664",
+      "displayName": "REDHAT6/64",
+      "family": "UNIX"
+    },
+    {
+      "id": "REDHAT764",
+      "displayName": "REDHAT7/64",
+      "family": "UNIX"
+    },
+    {
+      "id": "SLES1164",
+      "displayName": "SUSE11/64",
+      "family": "UNIX"
+    },
+    {
+      "id": "SUSE1164",
+      "displayName": "SUSE11/64",
+      "family": "UNIX"
+    },
+    {
+      "id": "UBUNTU1064",
+      "displayName": "UBUNTU10/64",
+      "family": "UNIX"
+    },
+    {
+      "id": "UBUNTU1264",
+      "displayName": "UBUNTU12/64",
+      "family": "UNIX"
+    },
+    {
+      "id": "UBUNTU1464",
+      "displayName": "UBUNTU14/64",
+      "family": "UNIX"
+    },
+    {
+      "id": "UBUNTU864",
+      "displayName": "UBUNTU8/64",
+      "family": "UNIX"
+    },
+    {
+      "id": "WIN2003E32",
+      "displayName": "WIN2003E/32",
+      "family": "WINDOWS"
+    },
+    {
+      "id": "WIN2003E64",
+      "displayName": "WIN2003E/64",
+      "family": "WINDOWS"
+    }
+  ],
+  "pageNumber": 1,
+  "pageCount": 20,
+  "totalCount": 33,
+  "pageSize": 20
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/84ebe3d3/dimensiondata/src/test/resources/operatingSystems-page2.json
----------------------------------------------------------------------
diff --git a/dimensiondata/src/test/resources/operatingSystems-page2.json 
b/dimensiondata/src/test/resources/operatingSystems-page2.json
new file mode 100644
index 0000000..e5ff282
--- /dev/null
+++ b/dimensiondata/src/test/resources/operatingSystems-page2.json
@@ -0,0 +1,73 @@
+{
+  "operatingSystem": [
+    {
+      "id": "WIN2003S32",
+      "displayName": "WIN2003S/32",
+      "family": "WINDOWS"
+    },
+    {
+      "id": "WIN2003S64",
+      "displayName": "WIN2003S/64",
+      "family": "WINDOWS"
+    },
+    {
+      "id": "WIN2008E32",
+      "displayName": "WIN2008E/32",
+      "family": "WINDOWS"
+    },
+    {
+      "id": "WIN2008E64",
+      "displayName": "WIN2008E/64",
+      "family": "WINDOWS"
+    },
+    {
+      "id": "WIN2008R2DC64",
+      "displayName": "WIN2008R2DC/64",
+      "family": "WINDOWS"
+    },
+    {
+      "id": "WIN2008R2E64",
+      "displayName": "WIN2008R2E/64",
+      "family": "WINDOWS"
+    },
+    {
+      "id": "WIN2008R2S64",
+      "displayName": "WIN2008R2S/64",
+      "family": "WINDOWS"
+    },
+    {
+      "id": "WIN2008S32",
+      "displayName": "WIN2008S/32",
+      "family": "WINDOWS"
+    },
+    {
+      "id": "WIN2008S64",
+      "displayName": "WIN2008S/64",
+      "family": "WINDOWS"
+    },
+    {
+      "id": "WIN2012DC64",
+      "displayName": "WIN2012DC/64",
+      "family": "WINDOWS"
+    },
+    {
+      "id": "WIN2012R2DC64",
+      "displayName": "WIN2012R2DC/64",
+      "family": "WINDOWS"
+    },
+    {
+      "id": "WIN2012R2S64",
+      "displayName": "WIN2012R2S/64",
+      "family": "WINDOWS"
+    },
+    {
+      "id": "WIN2012S64",
+      "displayName": "WIN2012S/64",
+      "family": "WINDOWS"
+    }
+  ],
+  "pageNumber": 2,
+  "pageCount": 13,
+  "totalCount": 33,
+  "pageSize": 20
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/84ebe3d3/dimensiondata/src/test/resources/operatingSystems.json
----------------------------------------------------------------------
diff --git a/dimensiondata/src/test/resources/operatingSystems.json 
b/dimensiondata/src/test/resources/operatingSystems.json
new file mode 100644
index 0000000..2a81439
--- /dev/null
+++ b/dimensiondata/src/test/resources/operatingSystems.json
@@ -0,0 +1,173 @@
+{
+  "operatingSystem": [
+    {
+      "id": "CENTOS532",
+      "displayName": "CENTOS5/32",
+      "family": "UNIX"
+    },
+    {
+      "id": "CENTOS564",
+      "displayName": "CENTOS5/64",
+      "family": "UNIX"
+    },
+    {
+      "id": "CENTOS632",
+      "displayName": "CENTOS6/32",
+      "family": "UNIX"
+    },
+    {
+      "id": "CENTOS664",
+      "displayName": "CENTOS6/64",
+      "family": "UNIX"
+    },
+    {
+      "id": "CENTOS764",
+      "displayName": "CENTOS7/64",
+      "family": "UNIX"
+    },
+    {
+      "id": "REDHAT432",
+      "displayName": "REDHAT4/32",
+      "family": "UNIX"
+    },
+    {
+      "id": "REDHAT464",
+      "displayName": "REDHAT4/64",
+      "family": "UNIX"
+    },
+    {
+      "id": "REDHAT532",
+      "displayName": "REDHAT5/32",
+      "family": "UNIX"
+    },
+    {
+      "id": "REDHAT564",
+      "displayName": "REDHAT5/64",
+      "family": "UNIX"
+    },
+    {
+      "id": "REDHAT632",
+      "displayName": "REDHAT6/32",
+      "family": "UNIX"
+    },
+    {
+      "id": "REDHAT664",
+      "displayName": "REDHAT6/64",
+      "family": "UNIX"
+    },
+    {
+      "id": "REDHAT764",
+      "displayName": "REDHAT7/64",
+      "family": "UNIX"
+    },
+    {
+      "id": "SLES1164",
+      "displayName": "SUSE11/64",
+      "family": "UNIX"
+    },
+    {
+      "id": "SUSE1164",
+      "displayName": "SUSE11/64",
+      "family": "UNIX"
+    },
+    {
+      "id": "UBUNTU1064",
+      "displayName": "UBUNTU10/64",
+      "family": "UNIX"
+    },
+    {
+      "id": "UBUNTU1264",
+      "displayName": "UBUNTU12/64",
+      "family": "UNIX"
+    },
+    {
+      "id": "UBUNTU1464",
+      "displayName": "UBUNTU14/64",
+      "family": "UNIX"
+    },
+    {
+      "id": "UBUNTU864",
+      "displayName": "UBUNTU8/64",
+      "family": "UNIX"
+    },
+    {
+      "id": "WIN2003E32",
+      "displayName": "WIN2003E/32",
+      "family": "WINDOWS"
+    },
+    {
+      "id": "WIN2003E64",
+      "displayName": "WIN2003E/64",
+      "family": "WINDOWS"
+    },
+    {
+      "id": "WIN2003S32",
+      "displayName": "WIN2003S/32",
+      "family": "WINDOWS"
+    },
+    {
+      "id": "WIN2003S64",
+      "displayName": "WIN2003S/64",
+      "family": "WINDOWS"
+    },
+    {
+      "id": "WIN2008E32",
+      "displayName": "WIN2008E/32",
+      "family": "WINDOWS"
+    },
+    {
+      "id": "WIN2008E64",
+      "displayName": "WIN2008E/64",
+      "family": "WINDOWS"
+    },
+    {
+      "id": "WIN2008R2DC64",
+      "displayName": "WIN2008R2DC/64",
+      "family": "WINDOWS"
+    },
+    {
+      "id": "WIN2008R2E64",
+      "displayName": "WIN2008R2E/64",
+      "family": "WINDOWS"
+    },
+    {
+      "id": "WIN2008R2S64",
+      "displayName": "WIN2008R2S/64",
+      "family": "WINDOWS"
+    },
+    {
+      "id": "WIN2008S32",
+      "displayName": "WIN2008S/32",
+      "family": "WINDOWS"
+    },
+    {
+      "id": "WIN2008S64",
+      "displayName": "WIN2008S/64",
+      "family": "WINDOWS"
+    },
+    {
+      "id": "WIN2012DC64",
+      "displayName": "WIN2012DC/64",
+      "family": "WINDOWS"
+    },
+    {
+      "id": "WIN2012R2DC64",
+      "displayName": "WIN2012R2DC/64",
+      "family": "WINDOWS"
+    },
+    {
+      "id": "WIN2012R2S64",
+      "displayName": "WIN2012R2S/64",
+      "family": "WINDOWS"
+    },
+    {
+      "id": "WIN2012S64",
+      "displayName": "WIN2012S/64",
+      "family": "WINDOWS"
+    }
+  ],
+  "pageNumber": 1,
+  "pageCount": 33,
+  "totalCount": 33,
+  "pageSize": 250
+}
\ No newline at end of file

Reply via email to