You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jclouds.apache.org by ab...@apache.org on 2013/07/01 21:14:49 UTC

[02/24] JCLOUDS-151 - CloudStack refactored to remove async, *Client renamed to *Api.

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/c6986efd/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/VirtualMachineClientLiveTest.java
----------------------------------------------------------------------
diff --git a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/VirtualMachineClientLiveTest.java b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/VirtualMachineClientLiveTest.java
deleted file mode 100644
index 15df50d..0000000
--- a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/VirtualMachineClientLiveTest.java
+++ /dev/null
@@ -1,399 +0,0 @@
-/*
- * 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.cloudstack.features;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-import static com.google.common.base.Predicates.in;
-import static com.google.common.collect.Iterables.find;
-import static com.google.common.collect.Iterables.get;
-import static com.google.common.collect.Iterables.getFirst;
-import static com.google.common.collect.Iterables.getOnlyElement;
-import static com.google.common.collect.Sets.filter;
-import static org.jclouds.cloudstack.options.ListNetworksOptions.Builder.isDefault;
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertTrue;
-
-import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.ExecutionException;
-import java.util.logging.Logger;
-
-import org.jclouds.cloudstack.CloudStackClient;
-import org.jclouds.cloudstack.domain.AsyncCreateResponse;
-import org.jclouds.cloudstack.domain.AsyncJob;
-import org.jclouds.cloudstack.domain.GuestIPType;
-import org.jclouds.cloudstack.domain.NIC;
-import org.jclouds.cloudstack.domain.Network;
-import org.jclouds.cloudstack.domain.NetworkOffering;
-import org.jclouds.cloudstack.domain.ServiceOffering;
-import org.jclouds.cloudstack.domain.Template;
-import org.jclouds.cloudstack.domain.VirtualMachine;
-import org.jclouds.cloudstack.domain.Zone;
-import org.jclouds.cloudstack.internal.BaseCloudStackClientLiveTest;
-import org.jclouds.cloudstack.options.CreateNetworkOptions;
-import org.jclouds.cloudstack.options.DeployVirtualMachineOptions;
-import org.jclouds.cloudstack.options.ListNetworkOfferingsOptions;
-import org.jclouds.cloudstack.options.ListNetworksOptions;
-import org.jclouds.cloudstack.options.ListTemplatesOptions;
-import org.jclouds.cloudstack.options.ListVirtualMachinesOptions;
-import org.jclouds.util.InetAddresses2;
-import org.testng.annotations.AfterGroups;
-import org.testng.annotations.Test;
-
-import com.google.common.base.Function;
-import com.google.common.base.Predicate;
-import com.google.common.base.Throwables;
-import com.google.common.collect.ComparisonChain;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Iterables;
-import com.google.common.collect.Maps;
-import com.google.common.collect.Ordering;
-import com.google.common.net.HostAndPort;
-import com.google.common.net.HostSpecifier;
-
-/**
- * Tests behavior of {@code VirtualMachineClientLiveTest}
- * 
- * @author Adrian Cole
- */
-@Test(groups = "live", singleThreaded = true, testName = "VirtualMachineClientLiveTest")
-public class VirtualMachineClientLiveTest extends BaseCloudStackClientLiveTest {
-   private static final Logger logger = Logger.getAnonymousLogger();
-
-   private VirtualMachine vm = null;
-
-   static final Ordering<ServiceOffering> DEFAULT_SIZE_ORDERING = new Ordering<ServiceOffering>() {
-      public int compare(ServiceOffering left, ServiceOffering right) {
-         return ComparisonChain.start().compare(left.getCpuNumber(), right.getCpuNumber())
-               .compare(left.getMemory(), right.getMemory()).result();
-      }
-   };
-
-   public static VirtualMachine createVirtualMachine(CloudStackClient client, String defaultTemplate,
-         Predicate<String> jobComplete, Predicate<VirtualMachine> virtualMachineRunning) {
-      Set<Network> networks = client.getNetworkClient().listNetworks(isDefault(true));
-      if (networks.size() > 0) {
-         Network network = get(filter(networks, new Predicate<Network>() {
-            @Override
-            public boolean apply(Network network) {
-               return network != null && network.getState().equals("Implemented");
-            }
-         }), 0);
-         return createVirtualMachineInNetwork(network,
-               defaultTemplateOrPreferredInZone(defaultTemplate, client, network.getZoneId()), client, jobComplete,
-               virtualMachineRunning);
-      } else {
-         String zoneId = find(client.getZoneClient().listZones(), new Predicate<Zone>() {
-
-            @Override
-            public boolean apply(Zone arg0) {
-               return arg0.isSecurityGroupsEnabled();
-            }
-
-         }).getId();
-         return createVirtualMachineWithSecurityGroupInZone(zoneId,
-               defaultTemplateOrPreferredInZone(defaultTemplate, client, zoneId),
-               get(client.getSecurityGroupClient().listSecurityGroups(), 0).getId(), client, jobComplete,
-               virtualMachineRunning);
-      }
-   }
-
-   public static VirtualMachine createVirtualMachineWithSecurityGroupInZone(String zoneId, String templateId, String groupId,
-         CloudStackClient client, Predicate<String> jobComplete,
-         Predicate<VirtualMachine> virtualMachineRunning) {
-      return createVirtualMachineWithOptionsInZone(new DeployVirtualMachineOptions().securityGroupId(groupId), zoneId,
-            templateId, client, jobComplete, virtualMachineRunning);
-   }
-
-   public static VirtualMachine createVirtualMachineInNetwork(Network network, String templateId,
-         CloudStackClient client, Predicate<String> jobComplete,
-         Predicate<VirtualMachine> virtualMachineRunning) {
-      DeployVirtualMachineOptions options = new DeployVirtualMachineOptions();
-      String zoneId = network.getZoneId();
-      options.networkId(network.getId());
-      return createVirtualMachineWithOptionsInZone(options, zoneId, templateId, client, jobComplete,
-            virtualMachineRunning);
-   }
-
-   public static VirtualMachine createVirtualMachineInNetworkWithIp(
-         CloudStackClient client, String templateId, Set<Network> networks, Map<String, String> ipToNetwork,
-         Predicate<String> jobComplete, Predicate<VirtualMachine> virtualMachineRunning) {
-
-      DeployVirtualMachineOptions options = new DeployVirtualMachineOptions();
-
-      String zoneId = getFirst(networks, null).getZoneId();
-      options.networkIds(Iterables.transform(networks, new Function<Network, String>() {
-         @Override
-         public String apply(Network network) {
-            return network.getId();
-         }
-      }));
-      options.ipsToNetworks(ipToNetwork);
-
-      return createVirtualMachineWithOptionsInZone(options, zoneId, templateId,
-         client, jobComplete, virtualMachineRunning);
-   }
-
-   public static VirtualMachine createVirtualMachineWithOptionsInZone(DeployVirtualMachineOptions options, String zoneId,
-         String templateId, CloudStackClient client, Predicate<String> jobComplete,
-         Predicate<VirtualMachine> virtualMachineRunning) {
-      String serviceOfferingId = DEFAULT_SIZE_ORDERING.min(client.getOfferingClient().listServiceOfferings()).getId();
-
-      System.out.printf("serviceOfferingId %s, templateId %s, zoneId %s, options %s%n", serviceOfferingId, templateId,
-            zoneId, options);
-      AsyncCreateResponse job = client.getVirtualMachineClient().deployVirtualMachineInZone(zoneId, serviceOfferingId,
-            templateId, options);
-      assertTrue(jobComplete.apply(job.getJobId()));
-      AsyncJob<VirtualMachine> jobWithResult = client.getAsyncJobClient().<VirtualMachine> getAsyncJob(job.getJobId());
-      if (jobWithResult.getError() != null)
-         Throwables.propagate(new ExecutionException(String.format("job %s failed with exception %s", job.getId(),
-               jobWithResult.getError().toString())) {
-         });
-      VirtualMachine vm = jobWithResult.getResult();
-      if (vm.isPasswordEnabled()) {
-         assert vm.getPassword() != null : vm;
-      }
-      assertTrue(virtualMachineRunning.apply(vm));
-      assertEquals(vm.getServiceOfferingId(), serviceOfferingId);
-      assertEquals(vm.getTemplateId(), templateId);
-      assertEquals(vm.getZoneId(), zoneId);
-      return vm;
-   }
-
-   @Test
-   public void testCreateVirtualMachine() throws Exception {
-      String defaultTemplate = template != null ? template.getImageId() : null;
-      vm = createVirtualMachine(client, defaultTemplate, jobComplete, virtualMachineRunning);
-      if (vm.getPassword() != null) {
-         conditionallyCheckSSH();
-      }
-      assert in(ImmutableSet.of("NetworkFilesystem", "IscsiLUN", "VMFS", "PreSetup"))
-         .apply(vm.getRootDeviceType()) : vm;
-      checkVm(vm);
-   }
-
-   @Test
-   public void testCreateVirtualMachineWithSpecificIp() throws Exception {
-      skipIfNotGlobalAdmin();
-
-      String defaultTemplate = template != null ? template.getImageId() : null;
-      Network network = null;
-
-      try {
-         Template template = getOnlyElement(
-            client.getTemplateClient().listTemplates(ListTemplatesOptions.Builder.id(defaultTemplate)));
-         logger.info("Using template: " + template);
-
-         Set<Network> allSafeNetworksInZone = adminClient.getNetworkClient().listNetworks(
-            ListNetworksOptions.Builder.zoneId(template.getZoneId()).isSystem(false));
-         for(Network net : allSafeNetworksInZone) {
-            if(net.getName().equals(prefix + "-ip-network")) {
-               logger.info("Deleting VMs in network: " + net);
-
-               Set<VirtualMachine> machinesInNetwork = adminClient.getVirtualMachineClient().listVirtualMachines(
-                  ListVirtualMachinesOptions.Builder.networkId(net.getId()));
-
-               for(VirtualMachine machine : machinesInNetwork) {
-                  if (machine.getState().equals(VirtualMachine.State.RUNNING)) {
-                     logger.info("Deleting VM: " + machine);
-                     destroyMachine(machine);
-                  }
-               }
-
-               assertTrue(adminJobComplete.apply(
-                  adminClient.getNetworkClient().deleteNetwork(net.getId())), net.toString());
-            }
-         }
-
-         NetworkOffering offering = getFirst(
-            client.getOfferingClient().listNetworkOfferings(
-               ListNetworkOfferingsOptions.Builder.zoneId(template.getZoneId()).specifyVLAN(true)), null);
-         checkNotNull(offering, "No network offering found");
-         logger.info("Using network offering: " + offering);
-
-         network = adminClient.getNetworkClient().createNetworkInZone(
-            template.getZoneId(), offering.getId(), prefix + "-ip-network", "",
-            CreateNetworkOptions.Builder.startIP("192.168.0.1").endIP("192.168.0.5")
-               .netmask("255.255.255.0").gateway("192.168.0.1").vlan("21"));
-         logger.info("Created network: " + network);
-
-         Network requiredNetwork = getOnlyElement(filter(adminClient.getNetworkClient().listNetworks(
-            ListNetworksOptions.Builder.zoneId(template.getZoneId())), new Predicate<Network>() {
-            @Override
-            public boolean apply(Network network) {
-               return network.isDefault() &&
-                  network.getGuestIPType() == GuestIPType.VIRTUAL;
-            }
-         }));
-         logger.info("Required network: " + requiredNetwork);
-
-         String ipAddress = "192.168.0.4";
-
-         Map<String, String> ipsToNetworks = Maps.newHashMap();
-         ipsToNetworks.put(ipAddress, network.getId());
-
-         vm = createVirtualMachineInNetworkWithIp(
-            adminClient, defaultTemplate, ImmutableSet.of(requiredNetwork, network),
-            ipsToNetworks, adminJobComplete, adminVirtualMachineRunning);
-         logger.info("Created VM: " + vm);
-
-         boolean hasStaticIpNic = false;
-         for(NIC nic : vm.getNICs()) {
-            if (nic.getNetworkId() == network.getId()) {
-               hasStaticIpNic = true;
-               assertEquals(nic.getIPAddress(), ipAddress);
-            }
-         }
-         assert hasStaticIpNic;
-         checkVm(vm);
-
-      } finally {
-         if (vm != null) {
-            destroyMachine(vm);
-            vm = null;
-         }
-         if (network != null) {
-            String jobId = adminClient.getNetworkClient().deleteNetwork(network.getId());
-            adminJobComplete.apply(jobId);
-            network = null;
-         }
-      }
-   }
-
-   private void destroyMachine(VirtualMachine virtualMachine) {
-      assertTrue(adminJobComplete.apply(
-         adminClient.getVirtualMachineClient().destroyVirtualMachine(virtualMachine.getId())), virtualMachine.toString());
-      assertTrue(adminVirtualMachineDestroyed.apply(virtualMachine));
-   }
-
-   private void conditionallyCheckSSH() {
-      if (vm.getPassword() != null && loginCredentials.getOptionalPassword() == null)
-         loginCredentials = loginCredentials.toBuilder().password(vm.getPassword()).build();
-      assert HostSpecifier.isValid(vm.getIPAddress());
-      if (!InetAddresses2.isPrivateIPAddress(vm.getIPAddress())) {
-         // not sure if the network is public or not, so we have to test
-         HostAndPort socket = HostAndPort.fromParts(vm.getIPAddress(), 22);
-         System.err.printf("testing socket %s%n", socket);
-         System.err.printf("testing ssh %s%n", socket);
-         checkSSH(socket);
-      } else {
-         System.err.printf("skipping ssh %s, as private%n", vm.getIPAddress());
-      }
-   }
-
-   @Test(dependsOnMethods = "testCreateVirtualMachine")
-   public void testLifeCycle() throws Exception {
-      String job = client.getVirtualMachineClient().stopVirtualMachine(vm.getId());
-      assertTrue(jobComplete.apply(job));
-      vm = client.getVirtualMachineClient().getVirtualMachine(vm.getId());
-      assertEquals(vm.getState(), VirtualMachine.State.STOPPED);
-
-      if (vm.isPasswordEnabled()) {
-         job = client.getVirtualMachineClient().resetPasswordForVirtualMachine(vm.getId());
-         assertTrue(jobComplete.apply(job));
-         vm = client.getAsyncJobClient().<VirtualMachine> getAsyncJob(job).getResult();
-         if (vm.getPassword() != null) {
-            conditionallyCheckSSH();
-         }
-      }
-
-      job = client.getVirtualMachineClient().startVirtualMachine(vm.getId());
-      assertTrue(jobComplete.apply(job));
-      vm = client.getVirtualMachineClient().getVirtualMachine(vm.getId());
-      assertEquals(vm.getState(), VirtualMachine.State.RUNNING);
-
-      job = client.getVirtualMachineClient().rebootVirtualMachine(vm.getId());
-      assertTrue(jobComplete.apply(job));
-      vm = client.getVirtualMachineClient().getVirtualMachine(vm.getId());
-      assertEquals(vm.getState(), VirtualMachine.State.RUNNING);
-   }
-
-   @AfterGroups(groups = "live")
-   @Override
-   protected void tearDownContext() {
-      if (vm != null) {
-         destroyMachine(vm);
-         vm = null;
-      }
-      super.tearDownContext();
-   }
-
-   @Test
-   public void testListVirtualMachines() throws Exception {
-      Set<VirtualMachine> response = client.getVirtualMachineClient().listVirtualMachines();
-      assert null != response;
-      assertTrue(response.size() >= 0);
-      for (VirtualMachine vm : response) {
-         VirtualMachine newDetails = getOnlyElement(client.getVirtualMachineClient().listVirtualMachines(
-               ListVirtualMachinesOptions.Builder.id(vm.getId())));
-         assertEquals(vm.getId(), newDetails.getId());
-         checkVm(vm);
-      }
-   }
-
-   protected void checkVm(VirtualMachine vm) {
-      assertEquals(vm.getId(), client.getVirtualMachineClient().getVirtualMachine(vm.getId()).getId());
-      assert vm.getId() != null : vm;
-      assert vm.getName() != null : vm;
-      assert vm.getDisplayName() != null : vm;
-      assert vm.getAccount() != null : vm;
-      assert vm.getDomain() != null : vm;
-      assert vm.getDomainId() != null : vm;
-      assert vm.getCreated() != null : vm;
-      assert vm.getState() != null : vm;
-      assert vm.getZoneId() != null : vm;
-      assert vm.getZoneName() != null : vm;
-      assert vm.getTemplateId() != null : vm;
-      assert vm.getTemplateName() != null : vm;
-      assert vm.getServiceOfferingId() != null : vm;
-      assert vm.getServiceOfferingName() != null : vm;
-      assert vm.getCpuCount() > 0 : vm;
-      assert vm.getCpuSpeed() > 0 : vm;
-      assert vm.getMemory() > 0 : vm;
-      assert vm.getGuestOSId() != null : vm;
-      assert vm.getRootDeviceId() != null : vm;
-      // assert vm.getRootDeviceType() != null : vm;
-      if (vm.getJobId() != null)
-         assert vm.getJobStatus() != null : vm;
-      assert vm.getNICs() != null && vm.getNICs().size() > 0 : vm;
-      for (NIC nic : vm.getNICs()) {
-         assert nic.getId() != null : vm;
-         assert nic.getNetworkId() != null : vm;
-         assert nic.getTrafficType() != null : vm;
-         assert nic.getGuestIPType() != null : vm;
-         switch (vm.getState()) {
-         case RUNNING:
-            assert nic.getNetmask() != null : vm;
-            assert nic.getGateway() != null : vm;
-            assert nic.getIPAddress() != null : vm;
-            break;
-         case STARTING:
-            assert nic.getNetmask() == null : vm;
-            assert nic.getGateway() == null : vm;
-            assert nic.getIPAddress() == null : vm;
-            break;
-         default:
-            assert nic.getNetmask() != null : vm;
-            assert nic.getGateway() != null : vm;
-            assert nic.getIPAddress() != null : vm;
-         }
-
-      }
-      assert vm.getSecurityGroups() != null && vm.getSecurityGroups().size() >= 0 : vm;
-      assert vm.getHypervisor() != null : vm;
-   }
-}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/c6986efd/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/VolumeApiExpectTest.java
----------------------------------------------------------------------
diff --git a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/VolumeApiExpectTest.java b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/VolumeApiExpectTest.java
new file mode 100644
index 0000000..288f3d5
--- /dev/null
+++ b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/VolumeApiExpectTest.java
@@ -0,0 +1,63 @@
+/*
+ * 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.cloudstack.features;
+
+import org.jclouds.cloudstack.CloudStackApiMetadata;
+import org.jclouds.cloudstack.CloudStackContext;
+import org.jclouds.cloudstack.domain.AsyncCreateResponse;
+import org.jclouds.cloudstack.internal.BaseCloudStackExpectTest;
+import org.jclouds.http.HttpRequest;
+import org.jclouds.http.HttpResponse;
+import org.testng.annotations.Test;
+
+import java.net.URI;
+import java.security.NoSuchAlgorithmException;
+import java.security.cert.CertificateException;
+
+import static org.testng.Assert.assertNotNull;
+
+/**
+* Test the CloudStack VolumeApi
+*
+* @author Adam Lowe
+*/
+@Test(groups = "unit", testName = "VolumeApiExpectTest")
+public class VolumeApiExpectTest extends BaseCloudStackExpectTest<VolumeApi> {
+
+   public void testCreateVolumeFromCustomDiskOffering() throws NoSuchAlgorithmException, CertificateException {
+      VolumeApi client = requestSendsResponse(
+              HttpRequest.builder()
+                      .method("GET")
+                      .endpoint(
+                              URI.create("http://localhost:8080/client/api?response=json&" +
+                                      "command=createVolume&name=VolumeApiExpectTest-jclouds-volume&diskofferingid=0473f5dd-bca5-4af4-a9b6-db9e8a88a2f6&zoneid=6f9a2921-b22a-4149-8b71-6ffc275a2177&size=1&apiKey=identity&signature=%2BoEjGobVFLr58k19LeAE81bZkKM%3D"))
+                      .addHeader("Accept", "application/json")
+                      .build(),
+              HttpResponse.builder()
+                      .statusCode(200)
+                      .payload(payloadFromResource("/queryasyncjobresultresponse-createvolume.json"))
+                      .build());
+      
+      AsyncCreateResponse response = client.createVolumeFromCustomDiskOfferingInZone("VolumeApiExpectTest-jclouds-volume", "0473f5dd-bca5-4af4-a9b6-db9e8a88a2f6", "6f9a2921-b22a-4149-8b71-6ffc275a2177", 1);
+      assertNotNull(response);
+   }
+
+   @Override
+   protected VolumeApi clientFrom(CloudStackContext context) {
+      return context.getApi().getVolumeApi();
+   }
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/c6986efd/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/VolumeApiLiveTest.java
----------------------------------------------------------------------
diff --git a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/VolumeApiLiveTest.java b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/VolumeApiLiveTest.java
new file mode 100644
index 0000000..755edad
--- /dev/null
+++ b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/VolumeApiLiveTest.java
@@ -0,0 +1,266 @@
+/*
+ * 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.cloudstack.features;
+
+import static org.testng.AssertJUnit.assertEquals;
+import static org.testng.AssertJUnit.assertFalse;
+import static org.testng.AssertJUnit.assertNotNull;
+import static org.testng.AssertJUnit.assertNotSame;
+import static org.testng.AssertJUnit.assertNull;
+import static org.testng.AssertJUnit.assertTrue;
+
+import java.util.NoSuchElementException;
+import java.util.Set;
+
+import javax.annotation.Resource;
+
+import org.jclouds.cloudstack.CloudStackApi;
+import org.jclouds.cloudstack.domain.AsyncCreateResponse;
+import org.jclouds.cloudstack.domain.DiskOffering;
+import org.jclouds.cloudstack.domain.Snapshot;
+import org.jclouds.cloudstack.domain.VirtualMachine;
+import org.jclouds.cloudstack.domain.Volume;
+import org.jclouds.cloudstack.domain.Zone;
+import org.jclouds.cloudstack.internal.BaseCloudStackApiLiveTest;
+import org.jclouds.cloudstack.options.ListVolumesOptions;
+import org.jclouds.logging.Logger;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import com.google.common.base.Function;
+import com.google.common.collect.Iterables;
+
+/**
+ * Tests behavior of {@code VolumeApi}
+ *
+ * @author Vijay Kiran, Alex Heneveld
+ */
+@Test(groups = "live", singleThreaded = true, testName = "VolumeApiLiveTest")
+public class VolumeApiLiveTest extends BaseCloudStackApiLiveTest {
+
+   @Resource Logger logger = Logger.NULL;
+
+   protected String prefix = System.getProperty("user.name")+"-"+getClass().getSimpleName();
+
+   private String zoneId;
+
+   @BeforeMethod(groups = "live")
+   public void setZoneId() {
+      Set<Zone> zones = client.getZoneApi().listZones();
+      assertNotNull(zones);
+      assertFalse(zones.isEmpty());
+      zoneId = Iterables.get(zones, 0).getId();
+   }
+
+   public void testListVolumes() {
+      Set<Volume> volumes = client.getVolumeApi().listVolumes();
+      assertNotNull(volumes);
+      assertFalse(volumes.isEmpty());
+
+      for (Volume volume : volumes) {
+         checkVolume(volume);
+      }
+   }
+
+   public void testListVolumesById() {
+      Iterable<String> volumeIds = Iterables.transform(client.getVolumeApi().listVolumes(), new Function<Volume, String>() {
+         public String apply(Volume input) {
+            return input.getId();
+         }
+      });
+      assertNotNull(volumeIds);
+      assertFalse(Iterables.isEmpty(volumeIds));
+
+      for (String id : volumeIds) {
+         Set<Volume> found = client.getVolumeApi().listVolumes(ListVolumesOptions.Builder.id(id));
+         assertNotNull(found);
+         assertEquals(1, found.size());
+         Volume volume = Iterables.getOnlyElement(found);
+         assertEquals(id, volume.getId());
+         checkVolume(volume);
+      }
+   }
+
+   public void testListVolumesNonexistantId() {
+      Set<Volume> found = client.getVolumeApi().listVolumes(ListVolumesOptions.Builder.id("foo"));
+      assertNotNull(found);
+      assertTrue(found.isEmpty());
+   }
+
+   public void testGetVolumeById() {
+      Iterable<String> volumeIds = Iterables.transform(client.getVolumeApi().listVolumes(), new Function<Volume, String>() {
+         public String apply(Volume input) {
+            return input.getId();
+         }
+      });
+      assertNotNull(volumeIds);
+      assertFalse(Iterables.isEmpty(volumeIds));
+
+      for (String id : volumeIds) {
+         Volume found = client.getVolumeApi().getVolume(id);
+         assertNotNull(found);
+         assertEquals(id, found.getId());
+         checkVolume(found);
+      }
+   }
+
+   public void testGetVolumeNonexistantId() {
+      Volume found = client.getVolumeApi().getVolume("foo");
+      assertNull(found);
+   }
+
+   protected DiskOffering getPreferredDiskOffering() {
+      for (DiskOffering candidate : client.getOfferingApi().listDiskOfferings()) {
+         //any will do
+         return candidate;
+      }
+      throw new AssertionError("No suitable DiskOffering found.");
+   }
+   protected Snapshot getPreferredSnapshot() {
+      for (Snapshot candidate : client.getSnapshotApi().listSnapshots()) {
+         if (candidate.getState()==Snapshot.State.BACKED_UP)
+            return candidate;
+      }
+      throw new AssertionError("No suitable Snapshot found.");
+   }
+
+   protected VirtualMachine getPreferredVirtualMachine() {
+      for (VirtualMachine candidate : client.getVirtualMachineApi().listVirtualMachines()) {
+//         this is a guess::
+         if (candidate.getState()==VirtualMachine.State.RUNNING || candidate.getState()==VirtualMachine.State.STOPPED)
+            return candidate;
+      }
+      throw new AssertionError("No suitable VirtualMachine found.");
+   }
+
+   protected Volume createPreferredVolumeFromDisk() {
+      AsyncCreateResponse job = client.getVolumeApi().createVolumeFromDiskOfferingInZone(prefix + "-jclouds-volume",
+            getPreferredDiskOffering().getId(), zoneId);
+      assertTrue(jobComplete.apply(job.getJobId()));
+      logger.info("created volume " + job.getId());
+      return findVolumeWithId(job.getId());
+   }
+
+   public void testCreateVolumeFromDiskofferingInZoneAndDeleteVolume() {
+      logger.info("testCreateVolumeFromDiskofferingInZoneAndDeleteVolume");
+      Volume volume = createPreferredVolumeFromDisk();
+      checkVolume(volume);
+      client.getVolumeApi().deleteVolume(volume.getId());
+   }
+
+   /** Test requires a custom disk offering to be available */
+   public void testCreateVolumeFromCustomDiskOffering() {
+      final int size = 1;
+      DiskOffering offering = null;
+      for (DiskOffering candidate : client.getOfferingApi().listDiskOfferings()) {
+         if (candidate.isCustomized()) {
+            offering = candidate;
+            break;
+         }
+      }
+      
+      assertNotNull("No custom disk offering found!", offering);
+      
+      AsyncCreateResponse job = client.getVolumeApi().createVolumeFromCustomDiskOfferingInZone(
+                prefix + "-jclouds-volume", offering.getId(), zoneId, size);
+      assertTrue(jobComplete.apply(job.getJobId()));
+      logger.info("created volume "+job.getId());
+      
+      Volume volume = findVolumeWithId(job.getId());
+      try {
+         checkVolume(volume);
+         assertEquals(volume.getSize(), size * 1024 * 1024 * 1024);
+      } finally {
+         client.getVolumeApi().deleteVolume(volume.getId());
+      }
+   }
+
+   /** test requires that a VM exist */
+   public void testCreateVolumeFromDiskofferingInZoneAndAttachVolumeToVirtualMachineAndDetachAndDelete() {
+      logger.info("testCreateVolumeFromDiskofferingInZoneAndAttachVolumeToVirtualMachineAndDetachAndDelete");
+      final Volume volume = createPreferredVolumeFromDisk();
+      try {
+
+         checkVolume(volume);
+
+         VirtualMachine virtualMachine = getPreferredVirtualMachine();
+
+         logger.info("attaching volume %s to vm %s", volume, virtualMachine);
+         AsyncCreateResponse job = client.getVolumeApi().attachVolume(volume.getId(), virtualMachine.getId());
+         assertTrue(jobComplete.apply(job.getJobId()));
+         Volume attachedVolume = findVolumeWithId(volume.getId());
+
+         checkVolume(attachedVolume);
+         assertEquals(virtualMachine.getId(), attachedVolume.getVirtualMachineId());
+         assertNotNull(attachedVolume.getAttached());
+
+         logger.info("detaching volume %s from vm %s", volume, virtualMachine);
+         job = client.getVolumeApi().detachVolume(volume.getId());
+         assertTrue(jobComplete.apply(job.getJobId()));
+         Volume detachedVolume = findVolumeWithId(volume.getId());
+
+         checkVolume(detachedVolume);
+         assertNull(detachedVolume.getAttached());
+
+      } finally {
+         client.getVolumeApi().deleteVolume(volume.getId());
+      }
+   }
+
+   public void testCreateVolumeFromSnapshotInZoneAndDeleteVolume() {
+      logger.info("testCreateVolumeFromSnapshotInZoneAndDeleteVolume (takes ~3m)");
+      assertNotNull(getPreferredSnapshot());
+
+      AsyncCreateResponse job = client.getVolumeApi().createVolumeFromSnapshotInZone(prefix + "-jclouds-volume",
+            getPreferredSnapshot().getId(), zoneId);
+      assertTrue(jobComplete.apply(job.getJobId()));
+      Volume volume = findVolumeWithId(job.getId());
+
+      checkVolume(volume);
+      client.getVolumeApi().deleteVolume(volume.getId());
+   }
+
+   static void checkVolume(final Volume volume) {
+      assertNotNull(volume.getId());
+      assertNotNull(volume.getName());
+      assertNotSame(Volume.Type.UNRECOGNIZED, volume.getType());
+   }
+
+   Volume findVolumeWithId(final String id) {
+      return findVolumeWithId(client, id);
+   }
+
+   static Volume findVolumeWithId(final CloudStackApi client, final String id) {
+      for (Volume v: client.getVolumeApi().listVolumes())
+         if (v.getId().equals(id)) return v;
+      throw new NoSuchElementException("no volume with id "+id);
+   }
+
+//   //uncomment to force a cleanup of volumes (since test failures can leave messes) 
+//   public void deleteAllWeUsed() {
+//      for (Volume v: client.getVolumeApi().listVolumes()) {
+//         if (v.getName().startsWith(prefix)) {
+//            logger.warn("found apparent detritus, deleting: %s", v);
+//            try {
+//               client.getVolumeApi().deleteVolume(v.getId());
+//            } catch (Exception e) {
+//               logger.warn(e, "failed to delete %s: %s", v, e);
+//            }
+//         }
+//       }
+//   }
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/c6986efd/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/VolumeApiTest.java
----------------------------------------------------------------------
diff --git a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/VolumeApiTest.java b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/VolumeApiTest.java
new file mode 100644
index 0000000..558dddd
--- /dev/null
+++ b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/VolumeApiTest.java
@@ -0,0 +1,164 @@
+/*
+ * 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.cloudstack.features;
+
+import static org.jclouds.reflect.Reflection2.method;
+
+import java.io.IOException;
+
+import org.jclouds.Fallbacks.EmptySetOnNotFoundOr404;
+import org.jclouds.Fallbacks.NullOnNotFoundOr404;
+import org.jclouds.Fallbacks.VoidOnNotFoundOr404;
+import org.jclouds.cloudstack.internal.BaseCloudStackApiTest;
+import org.jclouds.cloudstack.options.ListVolumesOptions;
+import org.jclouds.http.HttpRequest;
+import org.jclouds.rest.internal.GeneratedHttpRequest;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.reflect.Invokable;
+/**
+ * Tests behavior of {@code EventApi}
+ * 
+ * @author Vijay Kiran
+ */
+// NOTE:without testName, this will not call @Before* and fail w/NPE during
+// surefire
+@Test(groups = "unit", testName = "VolumeApiTest")
+public class VolumeApiTest extends BaseCloudStackApiTest<VolumeApi> {
+
+   public void testListVolumes() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(VolumeApi.class, "listVolumes", ListVolumesOptions[].class);
+      GeneratedHttpRequest httpRequest = processor.createRequest(method, ImmutableList.of());
+
+      assertRequestLineEquals(httpRequest,
+            "GET http://localhost:8080/client/api?response=json&command=listVolumes&listAll=true HTTP/1.1");
+      assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\n");
+      assertPayloadEquals(httpRequest, null, null, false);
+
+      assertSaxResponseParserClassEquals(method, null);
+      assertFallbackClassEquals(method, EmptySetOnNotFoundOr404.class);
+
+      checkFilters(httpRequest);
+
+   }
+
+   public void testGetVolume() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(VolumeApi.class, "getVolume", String.class);
+      GeneratedHttpRequest httpRequest = processor.createRequest(method, ImmutableList.<Object> of(111L));
+
+      assertRequestLineEquals(httpRequest,
+            "GET http://localhost:8080/client/api?response=json&command=listVolumes&listAll=true&id=111 HTTP/1.1");
+      assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\n");
+      assertPayloadEquals(httpRequest, null, null, false);
+
+      assertSaxResponseParserClassEquals(method, null);
+      assertFallbackClassEquals(method, NullOnNotFoundOr404.class);
+
+      checkFilters(httpRequest);
+
+   }
+
+   HttpRequest createVolumeFromSnapshot = HttpRequest.builder().method("GET")
+                                                     .endpoint("http://localhost:8080/client/api")
+                                                     .addQueryParam("response", "json")
+                                                     .addQueryParam("command", "createVolume")
+                                                     .addQueryParam("name", "jclouds-volume")
+                                                     .addQueryParam("snapshotid", "999")
+                                                     .addQueryParam("zoneid", "111").build();
+
+   public void testCreateVolumeWithSnapshot() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(VolumeApi.class, "createVolumeFromSnapshotInZone", String.class, String.class,
+            String.class);
+      GeneratedHttpRequest httpRequest = processor.createRequest(method, ImmutableList.<Object> of("jclouds-volume", 999L, 111l));
+
+      assertRequestLineEquals(httpRequest, createVolumeFromSnapshot.getRequestLine());
+      assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\n");
+      assertPayloadEquals(httpRequest, null, null, false);
+
+      assertSaxResponseParserClassEquals(method, null);
+      checkFilters(httpRequest);
+
+   }
+
+   HttpRequest createVolumeFromDiskOffering = HttpRequest.builder().method("GET")
+                                                         .endpoint("http://localhost:8080/client/api")
+                                                         .addQueryParam("response", "json")
+                                                         .addQueryParam("command", "createVolume")
+                                                         .addQueryParam("name", "jclouds-volume")
+                                                         .addQueryParam("diskofferingid", "999")
+                                                         .addQueryParam("zoneid", "111").build();
+
+   public void testCreateVolumeFromDiskOffering() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(VolumeApi.class, "createVolumeFromDiskOfferingInZone", String.class, String.class,
+            String.class);
+
+      GeneratedHttpRequest httpRequest = processor.createRequest(method, ImmutableList.<Object> of("jclouds-volume", 999L, 111L));
+
+      assertRequestLineEquals(httpRequest, createVolumeFromDiskOffering.getRequestLine());
+      assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\n");
+      assertPayloadEquals(httpRequest, null, null, false);
+
+      assertSaxResponseParserClassEquals(method, null);
+      checkFilters(httpRequest);
+
+   }
+
+   public void testAttachVolume() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(VolumeApi.class, "attachVolume", String.class, String.class);
+
+      GeneratedHttpRequest httpRequest = processor.createRequest(method, ImmutableList.<Object> of(111L, 999L));
+
+      assertRequestLineEquals(httpRequest,
+            "GET http://localhost:8080/client/api?response=json&command=attachVolume&id=111&virtualmachineid=999 HTTP/1.1");
+      assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\n");
+      assertPayloadEquals(httpRequest, null, null, false);
+
+      assertSaxResponseParserClassEquals(method, null);
+      checkFilters(httpRequest);
+
+   }
+
+   public void testDetachVolume() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(VolumeApi.class, "detachVolume", String.class);
+
+      GeneratedHttpRequest httpRequest = processor.createRequest(method, ImmutableList.<Object> of(111L));
+
+      assertRequestLineEquals(httpRequest,
+            "GET http://localhost:8080/client/api?response=json&command=detachVolume&id=111 HTTP/1.1");
+      assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\n");
+      assertPayloadEquals(httpRequest, null, null, false);
+
+      assertSaxResponseParserClassEquals(method, null);
+      checkFilters(httpRequest);
+
+   }
+
+   public void testDeleteVolume() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(VolumeApi.class, "deleteVolume", String.class);
+      GeneratedHttpRequest httpRequest = processor.createRequest(method, ImmutableList.<Object> of(111L));
+
+      assertRequestLineEquals(httpRequest,
+            "GET http://localhost:8080/client/api?response=json&command=deleteVolume&id=111 HTTP/1.1");
+      assertPayloadEquals(httpRequest, null, null, false);
+
+      assertSaxResponseParserClassEquals(method, null);
+      assertFallbackClassEquals(method, VoidOnNotFoundOr404.class);
+      checkFilters(httpRequest);
+
+   }
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/c6986efd/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/VolumeAsyncClientTest.java
----------------------------------------------------------------------
diff --git a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/VolumeAsyncClientTest.java b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/VolumeAsyncClientTest.java
deleted file mode 100644
index 1b2f506..0000000
--- a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/VolumeAsyncClientTest.java
+++ /dev/null
@@ -1,164 +0,0 @@
-/*
- * 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.cloudstack.features;
-
-import static org.jclouds.reflect.Reflection2.method;
-
-import java.io.IOException;
-
-import org.jclouds.Fallbacks.EmptySetOnNotFoundOr404;
-import org.jclouds.Fallbacks.NullOnNotFoundOr404;
-import org.jclouds.Fallbacks.VoidOnNotFoundOr404;
-import org.jclouds.cloudstack.internal.BaseCloudStackAsyncClientTest;
-import org.jclouds.cloudstack.options.ListVolumesOptions;
-import org.jclouds.http.HttpRequest;
-import org.jclouds.rest.internal.GeneratedHttpRequest;
-import org.testng.annotations.Test;
-
-import com.google.common.collect.ImmutableList;
-import com.google.common.reflect.Invokable;
-/**
- * Tests behavior of {@code EventAsyncClient}
- * 
- * @author Vijay Kiran
- */
-// NOTE:without testName, this will not call @Before* and fail w/NPE during
-// surefire
-@Test(groups = "unit", testName = "VolumeAsyncClientTest")
-public class VolumeAsyncClientTest extends BaseCloudStackAsyncClientTest<VolumeAsyncClient> {
-
-   public void testListVolumes() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(VolumeAsyncClient.class, "listVolumes", ListVolumesOptions[].class);
-      GeneratedHttpRequest httpRequest = processor.createRequest(method, ImmutableList.of());
-
-      assertRequestLineEquals(httpRequest,
-            "GET http://localhost:8080/client/api?response=json&command=listVolumes&listAll=true HTTP/1.1");
-      assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\n");
-      assertPayloadEquals(httpRequest, null, null, false);
-
-      assertSaxResponseParserClassEquals(method, null);
-      assertFallbackClassEquals(method, EmptySetOnNotFoundOr404.class);
-
-      checkFilters(httpRequest);
-
-   }
-
-   public void testGetVolume() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(VolumeAsyncClient.class, "getVolume", String.class);
-      GeneratedHttpRequest httpRequest = processor.createRequest(method, ImmutableList.<Object> of(111L));
-
-      assertRequestLineEquals(httpRequest,
-            "GET http://localhost:8080/client/api?response=json&command=listVolumes&listAll=true&id=111 HTTP/1.1");
-      assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\n");
-      assertPayloadEquals(httpRequest, null, null, false);
-
-      assertSaxResponseParserClassEquals(method, null);
-      assertFallbackClassEquals(method, NullOnNotFoundOr404.class);
-
-      checkFilters(httpRequest);
-
-   }
-
-   HttpRequest createVolumeFromSnapshot = HttpRequest.builder().method("GET")
-                                                     .endpoint("http://localhost:8080/client/api")
-                                                     .addQueryParam("response", "json")
-                                                     .addQueryParam("command", "createVolume")
-                                                     .addQueryParam("name", "jclouds-volume")
-                                                     .addQueryParam("snapshotid", "999")
-                                                     .addQueryParam("zoneid", "111").build();
-
-   public void testCreateVolumeWithSnapshot() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(VolumeAsyncClient.class, "createVolumeFromSnapshotInZone", String.class, String.class,
-            String.class);
-      GeneratedHttpRequest httpRequest = processor.createRequest(method, ImmutableList.<Object> of("jclouds-volume", 999L, 111l));
-
-      assertRequestLineEquals(httpRequest, createVolumeFromSnapshot.getRequestLine());
-      assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\n");
-      assertPayloadEquals(httpRequest, null, null, false);
-
-      assertSaxResponseParserClassEquals(method, null);
-      checkFilters(httpRequest);
-
-   }
-
-   HttpRequest createVolumeFromDiskOffering = HttpRequest.builder().method("GET")
-                                                         .endpoint("http://localhost:8080/client/api")
-                                                         .addQueryParam("response", "json")
-                                                         .addQueryParam("command", "createVolume")
-                                                         .addQueryParam("name", "jclouds-volume")
-                                                         .addQueryParam("diskofferingid", "999")
-                                                         .addQueryParam("zoneid", "111").build();
-
-   public void testCreateVolumeFromDiskOffering() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(VolumeAsyncClient.class, "createVolumeFromDiskOfferingInZone", String.class, String.class,
-            String.class);
-
-      GeneratedHttpRequest httpRequest = processor.createRequest(method, ImmutableList.<Object> of("jclouds-volume", 999L, 111L));
-
-      assertRequestLineEquals(httpRequest, createVolumeFromDiskOffering.getRequestLine());
-      assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\n");
-      assertPayloadEquals(httpRequest, null, null, false);
-
-      assertSaxResponseParserClassEquals(method, null);
-      checkFilters(httpRequest);
-
-   }
-
-   public void testAttachVolume() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(VolumeAsyncClient.class, "attachVolume", String.class, String.class);
-
-      GeneratedHttpRequest httpRequest = processor.createRequest(method, ImmutableList.<Object> of(111L, 999L));
-
-      assertRequestLineEquals(httpRequest,
-            "GET http://localhost:8080/client/api?response=json&command=attachVolume&id=111&virtualmachineid=999 HTTP/1.1");
-      assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\n");
-      assertPayloadEquals(httpRequest, null, null, false);
-
-      assertSaxResponseParserClassEquals(method, null);
-      checkFilters(httpRequest);
-
-   }
-
-   public void testDetachVolume() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(VolumeAsyncClient.class, "detachVolume", String.class);
-
-      GeneratedHttpRequest httpRequest = processor.createRequest(method, ImmutableList.<Object> of(111L));
-
-      assertRequestLineEquals(httpRequest,
-            "GET http://localhost:8080/client/api?response=json&command=detachVolume&id=111 HTTP/1.1");
-      assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\n");
-      assertPayloadEquals(httpRequest, null, null, false);
-
-      assertSaxResponseParserClassEquals(method, null);
-      checkFilters(httpRequest);
-
-   }
-
-   public void testDeleteVolume() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(VolumeAsyncClient.class, "deleteVolume", String.class);
-      GeneratedHttpRequest httpRequest = processor.createRequest(method, ImmutableList.<Object> of(111L));
-
-      assertRequestLineEquals(httpRequest,
-            "GET http://localhost:8080/client/api?response=json&command=deleteVolume&id=111 HTTP/1.1");
-      assertPayloadEquals(httpRequest, null, null, false);
-
-      assertSaxResponseParserClassEquals(method, null);
-      assertFallbackClassEquals(method, VoidOnNotFoundOr404.class);
-      checkFilters(httpRequest);
-
-   }
-}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/c6986efd/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/VolumeClientExpectTest.java
----------------------------------------------------------------------
diff --git a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/VolumeClientExpectTest.java b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/VolumeClientExpectTest.java
deleted file mode 100644
index f6b8f5d..0000000
--- a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/VolumeClientExpectTest.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * 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.cloudstack.features;
-
-import org.jclouds.cloudstack.CloudStackApiMetadata;
-import org.jclouds.cloudstack.CloudStackContext;
-import org.jclouds.cloudstack.domain.AsyncCreateResponse;
-import org.jclouds.cloudstack.internal.BaseCloudStackExpectTest;
-import org.jclouds.http.HttpRequest;
-import org.jclouds.http.HttpResponse;
-import org.testng.annotations.Test;
-
-import java.net.URI;
-import java.security.NoSuchAlgorithmException;
-import java.security.cert.CertificateException;
-
-import static org.testng.Assert.assertNotNull;
-
-/**
-* Test the CloudStack VolumeClient
-*
-* @author Adam Lowe
-*/
-@Test(groups = "unit", testName = "VolumeClientExpectTest")
-public class VolumeClientExpectTest extends BaseCloudStackExpectTest<VolumeClient> {
-
-   public void testCreateVolumeFromCustomDiskOffering() throws NoSuchAlgorithmException, CertificateException {
-      VolumeClient client = requestSendsResponse(
-              HttpRequest.builder()
-                      .method("GET")
-                      .endpoint(
-                              URI.create("http://localhost:8080/client/api?response=json&" +
-                                      "command=createVolume&name=VolumeClientExpectTest-jclouds-volume&diskofferingid=0473f5dd-bca5-4af4-a9b6-db9e8a88a2f6&zoneid=6f9a2921-b22a-4149-8b71-6ffc275a2177&size=1&apiKey=identity&signature=Y4%2BmdvhS/jlKRNSJ3nQqrjwg1CY%3D"))
-                      .addHeader("Accept", "application/json")
-                      .build(),
-              HttpResponse.builder()
-                      .statusCode(200)
-                      .payload(payloadFromResource("/queryasyncjobresultresponse-createvolume.json"))
-                      .build());
-      
-      AsyncCreateResponse response = client.createVolumeFromCustomDiskOfferingInZone("VolumeClientExpectTest-jclouds-volume", "0473f5dd-bca5-4af4-a9b6-db9e8a88a2f6", "6f9a2921-b22a-4149-8b71-6ffc275a2177", 1);
-      assertNotNull(response);
-   }
-
-   @Override
-   protected VolumeClient clientFrom(CloudStackContext context) {
-      return context.unwrap(CloudStackApiMetadata.CONTEXT_TOKEN).getApi().getVolumeClient();
-   }
-}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/c6986efd/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/VolumeClientLiveTest.java
----------------------------------------------------------------------
diff --git a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/VolumeClientLiveTest.java b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/VolumeClientLiveTest.java
deleted file mode 100644
index 5369dc0..0000000
--- a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/VolumeClientLiveTest.java
+++ /dev/null
@@ -1,266 +0,0 @@
-/*
- * 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.cloudstack.features;
-
-import static org.testng.AssertJUnit.assertEquals;
-import static org.testng.AssertJUnit.assertFalse;
-import static org.testng.AssertJUnit.assertNotNull;
-import static org.testng.AssertJUnit.assertNotSame;
-import static org.testng.AssertJUnit.assertNull;
-import static org.testng.AssertJUnit.assertTrue;
-
-import java.util.NoSuchElementException;
-import java.util.Set;
-
-import javax.annotation.Resource;
-
-import org.jclouds.cloudstack.CloudStackClient;
-import org.jclouds.cloudstack.domain.AsyncCreateResponse;
-import org.jclouds.cloudstack.domain.DiskOffering;
-import org.jclouds.cloudstack.domain.Snapshot;
-import org.jclouds.cloudstack.domain.VirtualMachine;
-import org.jclouds.cloudstack.domain.Volume;
-import org.jclouds.cloudstack.domain.Zone;
-import org.jclouds.cloudstack.internal.BaseCloudStackClientLiveTest;
-import org.jclouds.cloudstack.options.ListVolumesOptions;
-import org.jclouds.logging.Logger;
-import org.testng.annotations.BeforeMethod;
-import org.testng.annotations.Test;
-
-import com.google.common.base.Function;
-import com.google.common.collect.Iterables;
-
-/**
- * Tests behavior of {@code VolumeClient}
- *
- * @author Vijay Kiran, Alex Heneveld
- */
-@Test(groups = "live", singleThreaded = true, testName = "VolumeClientLiveTest")
-public class VolumeClientLiveTest extends BaseCloudStackClientLiveTest {
-
-   @Resource Logger logger = Logger.NULL;
-
-   protected String prefix = System.getProperty("user.name")+"-"+getClass().getSimpleName();
-
-   private String zoneId;
-
-   @BeforeMethod(groups = "live")
-   public void setZoneId() {
-      Set<Zone> zones = client.getZoneClient().listZones();
-      assertNotNull(zones);
-      assertFalse(zones.isEmpty());
-      zoneId = Iterables.get(zones, 0).getId();
-   }
-
-   public void testListVolumes() {
-      Set<Volume> volumes = client.getVolumeClient().listVolumes();
-      assertNotNull(volumes);
-      assertFalse(volumes.isEmpty());
-
-      for (Volume volume : volumes) {
-         checkVolume(volume);
-      }
-   }
-
-   public void testListVolumesById() {
-      Iterable<String> volumeIds = Iterables.transform(client.getVolumeClient().listVolumes(), new Function<Volume, String>() {
-         public String apply(Volume input) {
-            return input.getId();
-         }
-      });
-      assertNotNull(volumeIds);
-      assertFalse(Iterables.isEmpty(volumeIds));
-
-      for (String id : volumeIds) {
-         Set<Volume> found = client.getVolumeClient().listVolumes(ListVolumesOptions.Builder.id(id));
-         assertNotNull(found);
-         assertEquals(1, found.size());
-         Volume volume = Iterables.getOnlyElement(found);
-         assertEquals(id, volume.getId());
-         checkVolume(volume);
-      }
-   }
-
-   public void testListVolumesNonexistantId() {
-      Set<Volume> found = client.getVolumeClient().listVolumes(ListVolumesOptions.Builder.id("foo"));
-      assertNotNull(found);
-      assertTrue(found.isEmpty());
-   }
-
-   public void testGetVolumeById() {
-      Iterable<String> volumeIds = Iterables.transform(client.getVolumeClient().listVolumes(), new Function<Volume, String>() {
-         public String apply(Volume input) {
-            return input.getId();
-         }
-      });
-      assertNotNull(volumeIds);
-      assertFalse(Iterables.isEmpty(volumeIds));
-
-      for (String id : volumeIds) {
-         Volume found = client.getVolumeClient().getVolume(id);
-         assertNotNull(found);
-         assertEquals(id, found.getId());
-         checkVolume(found);
-      }
-   }
-
-   public void testGetVolumeNonexistantId() {
-      Volume found = client.getVolumeClient().getVolume("foo");
-      assertNull(found);
-   }
-
-   protected DiskOffering getPreferredDiskOffering() {
-      for (DiskOffering candidate : client.getOfferingClient().listDiskOfferings()) {
-         //any will do
-         return candidate;
-      }
-      throw new AssertionError("No suitable DiskOffering found.");
-   }
-   protected Snapshot getPreferredSnapshot() {
-      for (Snapshot candidate : client.getSnapshotClient().listSnapshots()) {
-         if (candidate.getState()==Snapshot.State.BACKED_UP)
-            return candidate;
-      }
-      throw new AssertionError("No suitable Snapshot found.");
-   }
-
-   protected VirtualMachine getPreferredVirtualMachine() {
-      for (VirtualMachine candidate : client.getVirtualMachineClient().listVirtualMachines()) {
-//         this is a guess::
-         if (candidate.getState()==VirtualMachine.State.RUNNING || candidate.getState()==VirtualMachine.State.STOPPED)
-            return candidate;
-      }
-      throw new AssertionError("No suitable VirtualMachine found.");
-   }
-
-   protected Volume createPreferredVolumeFromDisk() {
-      AsyncCreateResponse job = client.getVolumeClient().createVolumeFromDiskOfferingInZone(prefix + "-jclouds-volume",
-            getPreferredDiskOffering().getId(), zoneId);
-      assertTrue(jobComplete.apply(job.getJobId()));
-      logger.info("created volume " + job.getId());
-      return findVolumeWithId(job.getId());
-   }
-
-   public void testCreateVolumeFromDiskofferingInZoneAndDeleteVolume() {
-      logger.info("testCreateVolumeFromDiskofferingInZoneAndDeleteVolume");
-      Volume volume = createPreferredVolumeFromDisk();
-      checkVolume(volume);
-      client.getVolumeClient().deleteVolume(volume.getId());
-   }
-
-   /** Test requires a custom disk offering to be available */
-   public void testCreateVolumeFromCustomDiskOffering() {
-      final int size = 1;
-      DiskOffering offering = null;
-      for (DiskOffering candidate : client.getOfferingClient().listDiskOfferings()) {
-         if (candidate.isCustomized()) {
-            offering = candidate;
-            break;
-         }
-      }
-      
-      assertNotNull("No custom disk offering found!", offering);
-      
-      AsyncCreateResponse job = client.getVolumeClient().createVolumeFromCustomDiskOfferingInZone(
-                prefix + "-jclouds-volume", offering.getId(), zoneId, size);
-      assertTrue(jobComplete.apply(job.getJobId()));
-      logger.info("created volume "+job.getId());
-      
-      Volume volume = findVolumeWithId(job.getId());
-      try {
-         checkVolume(volume);
-         assertEquals(volume.getSize(), size * 1024 * 1024 * 1024);
-      } finally {
-         client.getVolumeClient().deleteVolume(volume.getId());
-      }
-   }
-
-   /** test requires that a VM exist */
-   public void testCreateVolumeFromDiskofferingInZoneAndAttachVolumeToVirtualMachineAndDetachAndDelete() {
-      logger.info("testCreateVolumeFromDiskofferingInZoneAndAttachVolumeToVirtualMachineAndDetachAndDelete");
-      final Volume volume = createPreferredVolumeFromDisk();
-      try {
-
-         checkVolume(volume);
-
-         VirtualMachine virtualMachine = getPreferredVirtualMachine();
-
-         logger.info("attaching volume %s to vm %s", volume, virtualMachine);
-         AsyncCreateResponse job = client.getVolumeClient().attachVolume(volume.getId(), virtualMachine.getId());
-         assertTrue(jobComplete.apply(job.getJobId()));
-         Volume attachedVolume = findVolumeWithId(volume.getId());
-
-         checkVolume(attachedVolume);
-         assertEquals(virtualMachine.getId(), attachedVolume.getVirtualMachineId());
-         assertNotNull(attachedVolume.getAttached());
-
-         logger.info("detaching volume %s from vm %s", volume, virtualMachine);
-         job = client.getVolumeClient().detachVolume(volume.getId());
-         assertTrue(jobComplete.apply(job.getJobId()));
-         Volume detachedVolume = findVolumeWithId(volume.getId());
-
-         checkVolume(detachedVolume);
-         assertNull(detachedVolume.getAttached());
-
-      } finally {
-         client.getVolumeClient().deleteVolume(volume.getId());
-      }
-   }
-
-   public void testCreateVolumeFromSnapshotInZoneAndDeleteVolume() {
-      logger.info("testCreateVolumeFromSnapshotInZoneAndDeleteVolume (takes ~3m)");
-      assertNotNull(getPreferredSnapshot());
-
-      AsyncCreateResponse job = client.getVolumeClient().createVolumeFromSnapshotInZone(prefix + "-jclouds-volume",
-            getPreferredSnapshot().getId(), zoneId);
-      assertTrue(jobComplete.apply(job.getJobId()));
-      Volume volume = findVolumeWithId(job.getId());
-
-      checkVolume(volume);
-      client.getVolumeClient().deleteVolume(volume.getId());
-   }
-
-   static void checkVolume(final Volume volume) {
-      assertNotNull(volume.getId());
-      assertNotNull(volume.getName());
-      assertNotSame(Volume.Type.UNRECOGNIZED, volume.getType());
-   }
-
-   Volume findVolumeWithId(final String id) {
-      return findVolumeWithId(client, id);
-   }
-
-   static Volume findVolumeWithId(final CloudStackClient client, final String id) {
-      for (Volume v: client.getVolumeClient().listVolumes())
-         if (v.getId().equals(id)) return v;
-      throw new NoSuchElementException("no volume with id "+id);
-   }
-
-//   //uncomment to force a cleanup of volumes (since test failures can leave messes) 
-//   public void deleteAllWeUsed() {
-//      for (Volume v: client.getVolumeClient().listVolumes()) {
-//         if (v.getName().startsWith(prefix)) {
-//            logger.warn("found apparent detritus, deleting: %s", v);
-//            try {
-//               client.getVolumeClient().deleteVolume(v.getId());
-//            } catch (Exception e) {
-//               logger.warn(e, "failed to delete %s: %s", v, e);
-//            }
-//         }
-//       }
-//   }
-}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/c6986efd/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/ZoneApiExpectTest.java
----------------------------------------------------------------------
diff --git a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/ZoneApiExpectTest.java b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/ZoneApiExpectTest.java
new file mode 100644
index 0000000..bd9479d
--- /dev/null
+++ b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/ZoneApiExpectTest.java
@@ -0,0 +1,93 @@
+/*
+ * 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.cloudstack.features;
+
+import static org.testng.Assert.assertEquals;
+
+import java.net.URI;
+
+import org.jclouds.cloudstack.CloudStackApiMetadata;
+import org.jclouds.cloudstack.CloudStackContext;
+import org.jclouds.cloudstack.domain.NetworkType;
+import org.jclouds.cloudstack.domain.Zone;
+import org.jclouds.cloudstack.internal.BaseCloudStackExpectTest;
+import org.jclouds.http.HttpRequest;
+import org.jclouds.http.HttpResponse;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.ImmutableSet;
+
+/**
+ * Test the CloudStack ZoneApi
+ *
+ * @author Andrei Savu
+ */
+@Test(groups = "unit", testName = "ZoneApiExpectTest")
+public class ZoneApiExpectTest extends BaseCloudStackExpectTest<ZoneApi> {
+
+
+   public void testListZonesWhenResponseIs2xx() {
+      ZoneApi client = requestSendsResponse(
+         HttpRequest.builder().method("GET")
+                    .endpoint("http://localhost:8080/client/api")
+                    .addQueryParam("response", "json")
+                    .addQueryParam("command", "listZones")
+                    .addQueryParam("listAll", "true")
+                    .addQueryParam("apiKey", "identity")
+                    .addQueryParam("signature", "8iHCtck0qfxFTqJ8reyAObRf31I%3D")
+                    .addHeader("Accept", "application/json")
+                    .build(),
+         HttpResponse.builder()
+                     .statusCode(200)
+                     .payload(payloadFromResource("/listzonesresponse.json"))
+                     .build());
+
+      assertEquals(client.listZones(),
+         ImmutableSet.of(
+            Zone.builder()
+               .id("1")
+               .name("San Jose 1")
+               .networkType(NetworkType.ADVANCED)
+               .securityGroupsEnabled(false).build(),
+            Zone.builder()
+               .id("2")
+               .name("Chicago")
+               .networkType(NetworkType.ADVANCED)
+               .securityGroupsEnabled(true).build()));
+   }
+
+   public void testListZonesWhenResponseIs404() {
+      ZoneApi client = requestSendsResponse(
+         HttpRequest.builder()
+            .method("GET")
+            .endpoint(
+               URI.create("http://localhost:8080/client/api?response=json&" +
+                  "command=listZones&listAll=true&apiKey=identity&signature=8iHCtck0qfxFTqJ8reyAObRf31I%3D"))
+            .addHeader("Accept", "application/json")
+            .build(),
+         HttpResponse.builder()
+            .statusCode(404)
+            .build());
+
+      assertEquals(client.listZones(), ImmutableSet.of());
+   }
+
+   @Override
+   protected ZoneApi clientFrom(CloudStackContext context) {
+      return context.getApi().getZoneApi();
+   }
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/c6986efd/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/ZoneApiLiveTest.java
----------------------------------------------------------------------
diff --git a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/ZoneApiLiveTest.java b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/ZoneApiLiveTest.java
new file mode 100644
index 0000000..1739396
--- /dev/null
+++ b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/ZoneApiLiveTest.java
@@ -0,0 +1,74 @@
+/*
+ * 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.cloudstack.features;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+
+import java.util.Set;
+
+import org.jclouds.cloudstack.domain.NetworkType;
+import org.jclouds.cloudstack.domain.Zone;
+import org.jclouds.cloudstack.internal.BaseCloudStackApiLiveTest;
+import org.jclouds.cloudstack.options.ListZonesOptions;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.Iterables;
+
+/**
+ * Tests behavior of {@code ZoneApiLiveTest}
+ * 
+ * @author Adrian Cole
+ */
+@Test(groups = "live", singleThreaded = true, testName = "ZoneApiLiveTest")
+public class ZoneApiLiveTest extends BaseCloudStackApiLiveTest {
+
+   public void testListZones() throws Exception {
+      Set<Zone> response = client.getZoneApi().listZones();
+      assert null != response;
+      long zoneCount = response.size();
+      assertTrue(zoneCount >= 0);
+      for (Zone zone : response) {
+         Zone newDetails = Iterables.getOnlyElement(client.getZoneApi().listZones(
+               ListZonesOptions.Builder.id(zone.getId())));
+         assertEquals(zone, newDetails);
+         assertEquals(zone, client.getZoneApi().getZone(zone.getId()));
+         assert zone.getId() != null : zone;
+         assert zone.getName() != null : zone;
+         assert zone.getNetworkType() != null && zone.getNetworkType() != NetworkType.UNRECOGNIZED : zone;
+         switch (zone.getNetworkType()) {
+         case ADVANCED:
+            // TODO
+            // assert zone.getVLAN() != null : zone;
+            // assert zone.getDomain() == null : zone;
+            // assert zone.getDomainId() == null : zone;
+            // assert zone.getGuestCIDRAddress() != null : zone;
+            break;
+         case BASIC:
+            assert zone.getVLAN() == null : zone;
+            assert zone.getDNS().size() >= 0 : zone;
+            assert zone.getInternalDNS().size() >= 0 : zone;
+            assert zone.getDomain() == null : zone;
+            assert zone.getDomainId() == null : zone;
+            assert zone.getGuestCIDRAddress() == null : zone;
+            break;
+         }
+
+      }
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/c6986efd/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/ZoneApiTest.java
----------------------------------------------------------------------
diff --git a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/ZoneApiTest.java b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/ZoneApiTest.java
new file mode 100644
index 0000000..9958e9d
--- /dev/null
+++ b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/ZoneApiTest.java
@@ -0,0 +1,107 @@
+/*
+ * 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.cloudstack.features;
+
+import static org.jclouds.reflect.Reflection2.method;
+
+import java.io.IOException;
+
+import org.jclouds.Fallbacks.EmptySetOnNotFoundOr404;
+import org.jclouds.Fallbacks.NullOnNotFoundOr404;
+import org.jclouds.cloudstack.internal.BaseCloudStackApiTest;
+import org.jclouds.cloudstack.options.ListZonesOptions;
+import org.jclouds.functions.IdentityFunction;
+import org.jclouds.http.functions.ParseFirstJsonValueNamed;
+import org.jclouds.rest.internal.GeneratedHttpRequest;
+import org.testng.annotations.Test;
+
+import com.google.common.base.Functions;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Iterables;
+import com.google.common.reflect.Invokable;
+/**
+ * Tests behavior of {@code ZoneApi}
+ * 
+ * @author Adrian Cole
+ */
+// NOTE:without testName, this will not call @Before* and fail w/NPE during
+// surefire
+@Test(groups = "unit", testName = "ZoneApiTest")
+public class ZoneApiTest extends BaseCloudStackApiTest<ZoneApi> {
+   public void testListZones() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(ZoneApi.class, "listZones", ListZonesOptions[].class);
+      GeneratedHttpRequest httpRequest = processor.createRequest(method, ImmutableList.of());
+
+      assertRequestLineEquals(httpRequest,
+            "GET http://localhost:8080/client/api?response=json&command=listZones&listAll=true HTTP/1.1");
+      assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\n");
+      assertPayloadEquals(httpRequest, null, null, false);
+
+      // now make sure request filters apply by replaying
+      httpRequest = (GeneratedHttpRequest) Iterables.getOnlyElement(httpRequest.getFilters()).filter(httpRequest);
+      httpRequest = (GeneratedHttpRequest) Iterables.getOnlyElement(httpRequest.getFilters()).filter(httpRequest);
+
+      assertRequestLineEquals(
+            httpRequest,
+            "GET http://localhost:8080/client/api?response=json&command=listZones&listAll=true&apiKey=identity&signature=8iHCtck0qfxFTqJ8reyAObRf31I%3D HTTP/1.1");
+      assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\n");
+      assertPayloadEquals(httpRequest, null, null, false);
+
+      assertResponseParserClassEquals(method, httpRequest, ParseFirstJsonValueNamed.class);
+      assertSaxResponseParserClassEquals(method, null);
+      assertFallbackClassEquals(method, EmptySetOnNotFoundOr404.class);
+
+      checkFilters(httpRequest);
+
+   }
+
+   public void testListZonesOptions() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(ZoneApi.class, "listZones", ListZonesOptions[].class);
+      GeneratedHttpRequest httpRequest = processor.createRequest(method, ImmutableList.<Object> of(ListZonesOptions.Builder.available(true).domainId("5")
+            .id("6")));
+
+      assertRequestLineEquals(httpRequest,
+            "GET http://localhost:8080/client/api?response=json&command=listZones&listAll=true&available=true&domainid=5&id=6 HTTP/1.1");
+      assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\n");
+      assertPayloadEquals(httpRequest, null, null, false);
+
+      assertResponseParserClassEquals(method, httpRequest, ParseFirstJsonValueNamed.class);
+      assertSaxResponseParserClassEquals(method, null);
+      assertFallbackClassEquals(method, EmptySetOnNotFoundOr404.class);
+
+      checkFilters(httpRequest);
+
+   }
+
+   public void testGetZone() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(ZoneApi.class, "getZone", String.class);
+      GeneratedHttpRequest httpRequest = processor.createRequest(method, ImmutableList.<Object> of(6));
+
+      assertRequestLineEquals(httpRequest,
+            "GET http://localhost:8080/client/api?response=json&command=listZones&listAll=true&id=6 HTTP/1.1");
+      assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\n");
+      assertPayloadEquals(httpRequest, null, null, false);
+
+      assertResponseParserClassEquals(method, httpRequest,
+            Functions.compose(IdentityFunction.INSTANCE, IdentityFunction.INSTANCE).getClass());
+      assertSaxResponseParserClassEquals(method, null);
+      assertFallbackClassEquals(method, NullOnNotFoundOr404.class);
+
+      checkFilters(httpRequest);
+
+   }
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/c6986efd/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/ZoneAsyncClientTest.java
----------------------------------------------------------------------
diff --git a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/ZoneAsyncClientTest.java b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/ZoneAsyncClientTest.java
deleted file mode 100644
index 0774c70..0000000
--- a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/ZoneAsyncClientTest.java
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * 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.cloudstack.features;
-
-import static org.jclouds.reflect.Reflection2.method;
-
-import java.io.IOException;
-
-import org.jclouds.Fallbacks.EmptySetOnNotFoundOr404;
-import org.jclouds.Fallbacks.NullOnNotFoundOr404;
-import org.jclouds.cloudstack.internal.BaseCloudStackAsyncClientTest;
-import org.jclouds.cloudstack.options.ListZonesOptions;
-import org.jclouds.functions.IdentityFunction;
-import org.jclouds.http.functions.ParseFirstJsonValueNamed;
-import org.jclouds.rest.internal.GeneratedHttpRequest;
-import org.testng.annotations.Test;
-
-import com.google.common.base.Functions;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.Iterables;
-import com.google.common.reflect.Invokable;
-/**
- * Tests behavior of {@code ZoneAsyncClient}
- * 
- * @author Adrian Cole
- */
-// NOTE:without testName, this will not call @Before* and fail w/NPE during
-// surefire
-@Test(groups = "unit", testName = "ZoneAsyncClientTest")
-public class ZoneAsyncClientTest extends BaseCloudStackAsyncClientTest<ZoneAsyncClient> {
-   public void testListZones() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(ZoneAsyncClient.class, "listZones", ListZonesOptions[].class);
-      GeneratedHttpRequest httpRequest = processor.createRequest(method, ImmutableList.of());
-
-      assertRequestLineEquals(httpRequest,
-            "GET http://localhost:8080/client/api?response=json&command=listZones&listAll=true HTTP/1.1");
-      assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\n");
-      assertPayloadEquals(httpRequest, null, null, false);
-
-      // now make sure request filters apply by replaying
-      httpRequest = (GeneratedHttpRequest) Iterables.getOnlyElement(httpRequest.getFilters()).filter(httpRequest);
-      httpRequest = (GeneratedHttpRequest) Iterables.getOnlyElement(httpRequest.getFilters()).filter(httpRequest);
-
-      assertRequestLineEquals(
-            httpRequest,
-            "GET http://localhost:8080/client/api?response=json&command=listZones&listAll=true&apiKey=identity&signature=8iHCtck0qfxFTqJ8reyAObRf31I%3D HTTP/1.1");
-      assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\n");
-      assertPayloadEquals(httpRequest, null, null, false);
-
-      assertResponseParserClassEquals(method, httpRequest, ParseFirstJsonValueNamed.class);
-      assertSaxResponseParserClassEquals(method, null);
-      assertFallbackClassEquals(method, EmptySetOnNotFoundOr404.class);
-
-      checkFilters(httpRequest);
-
-   }
-
-   public void testListZonesOptions() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(ZoneAsyncClient.class, "listZones", ListZonesOptions[].class);
-      GeneratedHttpRequest httpRequest = processor.createRequest(method, ImmutableList.<Object> of(ListZonesOptions.Builder.available(true).domainId("5")
-            .id("6")));
-
-      assertRequestLineEquals(httpRequest,
-            "GET http://localhost:8080/client/api?response=json&command=listZones&listAll=true&available=true&domainid=5&id=6 HTTP/1.1");
-      assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\n");
-      assertPayloadEquals(httpRequest, null, null, false);
-
-      assertResponseParserClassEquals(method, httpRequest, ParseFirstJsonValueNamed.class);
-      assertSaxResponseParserClassEquals(method, null);
-      assertFallbackClassEquals(method, EmptySetOnNotFoundOr404.class);
-
-      checkFilters(httpRequest);
-
-   }
-
-   public void testGetZone() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(ZoneAsyncClient.class, "getZone", String.class);
-      GeneratedHttpRequest httpRequest = processor.createRequest(method, ImmutableList.<Object> of(6));
-
-      assertRequestLineEquals(httpRequest,
-            "GET http://localhost:8080/client/api?response=json&command=listZones&listAll=true&id=6 HTTP/1.1");
-      assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\n");
-      assertPayloadEquals(httpRequest, null, null, false);
-
-      assertResponseParserClassEquals(method, httpRequest,
-            Functions.compose(IdentityFunction.INSTANCE, IdentityFunction.INSTANCE).getClass());
-      assertSaxResponseParserClassEquals(method, null);
-      assertFallbackClassEquals(method, NullOnNotFoundOr404.class);
-
-      checkFilters(httpRequest);
-
-   }
-}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/c6986efd/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/ZoneClientExpectTest.java
----------------------------------------------------------------------
diff --git a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/ZoneClientExpectTest.java b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/ZoneClientExpectTest.java
deleted file mode 100644
index 55f9a9e..0000000
--- a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/ZoneClientExpectTest.java
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * 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.cloudstack.features;
-
-import static org.testng.Assert.assertEquals;
-
-import java.net.URI;
-
-import org.jclouds.cloudstack.CloudStackApiMetadata;
-import org.jclouds.cloudstack.CloudStackContext;
-import org.jclouds.cloudstack.domain.NetworkType;
-import org.jclouds.cloudstack.domain.Zone;
-import org.jclouds.cloudstack.internal.BaseCloudStackExpectTest;
-import org.jclouds.http.HttpRequest;
-import org.jclouds.http.HttpResponse;
-import org.testng.annotations.Test;
-
-import com.google.common.collect.ImmutableSet;
-
-/**
- * Test the CloudStack ZoneClient
- *
- * @author Andrei Savu
- */
-@Test(groups = "unit", testName = "ZoneClientExpectTest")
-public class ZoneClientExpectTest extends BaseCloudStackExpectTest<ZoneClient> {
-
-
-   public void testListZonesWhenResponseIs2xx() {
-      ZoneClient client = requestSendsResponse(
-         HttpRequest.builder().method("GET")
-                    .endpoint("http://localhost:8080/client/api")
-                    .addQueryParam("response", "json")
-                    .addQueryParam("command", "listZones")
-                    .addQueryParam("listAll", "true")
-                    .addQueryParam("apiKey", "identity")
-                    .addQueryParam("signature", "8iHCtck0qfxFTqJ8reyAObRf31I%3D")
-                    .addHeader("Accept", "application/json")
-                    .build(),
-         HttpResponse.builder()
-                     .statusCode(200)
-                     .payload(payloadFromResource("/listzonesresponse.json"))
-                     .build());
-
-      assertEquals(client.listZones(),
-         ImmutableSet.of(
-            Zone.builder()
-               .id("1")
-               .name("San Jose 1")
-               .networkType(NetworkType.ADVANCED)
-               .securityGroupsEnabled(false).build(),
-            Zone.builder()
-               .id("2")
-               .name("Chicago")
-               .networkType(NetworkType.ADVANCED)
-               .securityGroupsEnabled(true).build()));
-   }
-
-   public void testListZonesWhenResponseIs404() {
-      ZoneClient client = requestSendsResponse(
-         HttpRequest.builder()
-            .method("GET")
-            .endpoint(
-               URI.create("http://localhost:8080/client/api?response=json&" +
-                  "command=listZones&listAll=true&apiKey=identity&signature=8iHCtck0qfxFTqJ8reyAObRf31I%3D"))
-            .addHeader("Accept", "application/json")
-            .build(),
-         HttpResponse.builder()
-            .statusCode(404)
-            .build());
-
-      assertEquals(client.listZones(), ImmutableSet.of());
-   }
-
-   @Override
-   protected ZoneClient clientFrom(CloudStackContext context) {
-      return context.unwrap(CloudStackApiMetadata.CONTEXT_TOKEN).getApi().getZoneClient();
-   }
-}