Example of Dimension Data CloudControl provider
diff --git a/blobstore-uploader/dependency-reduced-pom.xml b/blobstore-uploader/dependency-reduced-pom.xml
index 2a895db..a5ca3ad 100644
--- a/blobstore-uploader/dependency-reduced-pom.xml
+++ b/blobstore-uploader/dependency-reduced-pom.xml
@@ -34,4 +34,3 @@
     <jclouds.version>2.1.0</jclouds.version>

   </properties>

 </project>

-

diff --git a/compute-basics/pom.xml b/compute-basics/pom.xml
index 088eb88..217da90 100644
--- a/compute-basics/pom.xml
+++ b/compute-basics/pom.xml
@@ -41,6 +41,11 @@
       <artifactId>jclouds-allcompute</artifactId>
       <version>${jclouds.version}</version>
     </dependency>
+    <dependency>
+        <groupId>org.apache.jclouds.labs</groupId>
+        <artifactId>dimensiondata-cloudcontrol</artifactId>
+        <version>2.2.0-SNAPSHOT</version>
+    </dependency>
     <!-- note that if you want a smaller distribution
          remove the above dependency and place something 
          like below -->
diff --git a/dimensiondata/README.md b/dimensiondata/README.md
new file mode 100644
index 0000000..54a379b
--- /dev/null
+++ b/dimensiondata/README.md
@@ -0,0 +1,57 @@
+# Dimension Data Examples
+Example code that uses jclouds to perform common tasks on an Dimension Data CloudControl. The class names are self-explanatory and the code is well commented for you to follow along.
+
+- [Requirements](#requirements)
+- [Environment](#environment)
+- [The Examples](#examples)
+- [Support and Feedback](#support-and-feedback)
+
+## Requirements
+
+1. Username and password for Dimension Data CloudControl - See the [Getting Started guide](http://jclouds.apache.org/guides/dimensiondata/).
+1. Java Development Kit (JDK) version 6 or later - [Download](http://www.oracle.com/technetwork/java/javase/downloads/index.html).
+1. Apache Maven - [Maven in 5 Minutes](http://maven.apache.org/guides/getting-started/maven-in-five-minutes.html).
+1. Git - [Download](http://git-scm.com/downloads).
+
+## Environment
+To setup an environment to compile and run the examples use these commands:
+
+```
+git clone https://github.com/jclouds/jclouds-examples.git
+cd jclouds-examples/dimensiondata/
+```
+
+To package the examples jar file and dependencies run:
+
+```
+mvn package
+```
+
+## Examples
+
+To run individual examples from the command line use these commands:
+
+Every example class has a main method that takes the following arguments in the listed order:
+
+1. API Endpoint
+1. Username
+1. Password
+
+If there are other arguments required they will follow. The command line format looks like this:
+```
+java -cp target\dimensiondata-cloudcontrol-examples-<VERSION>-jar-with-dependencies.jar <MAIN_CLASS> apiEndpoint username password <PARAMETERS>
+```
+
+Try out an example.
+
+```
+java -cp target\dimensiondata-cloudcontrol-examples-<VERSION>-jar-with-dependencies.jar org.jclouds.examples.dimensiondata.cloudcontrol.DeployNetworkDomainVlanAndServer apiEndpoint username password
+```
+
+Watch the terminal for output!
+
+## Support and Feedback
+
+Your feedback is appreciated! If you have specific issues with Dimension Data CloudControl support in jclouds, we'd prefer that you file an issue via [JIRA](https://issues.apache.org/jira/browse/JCLOUDS).
+
+If you have questions or need help, please join our [community](http://jclouds.apache.org/community/) and subscribe to the jclouds user mailing list.
diff --git a/dimensiondata/pom.xml b/dimensiondata/pom.xml
new file mode 100644
index 0000000..8dcb1c2
--- /dev/null
+++ b/dimensiondata/pom.xml
@@ -0,0 +1,100 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You under the Apache License, Version 2.0
+    (the "License"); you may not use this file except in compliance with
+    the License.  You may obtain a copy of the License at
+
+        http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <groupId>org.apache.jclouds.examples</groupId>
+        <artifactId>jclouds-examples</artifactId>
+        <version>2.2.0-SNAPSHOT</version>
+    </parent>
+
+    <artifactId>dimensiondata-cloudcontrol-examples</artifactId>
+    <name>dimensiondata-cloudcontrol-examples</name>
+    <version>2.2.0-SNAPSHOT</version>
+
+    <properties>
+        <jclouds.version>2.2.0-SNAPSHOT</jclouds.version>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.jclouds.labs</groupId>
+            <artifactId>dimensiondata-cloudcontrol</artifactId>
+            <version>${jclouds.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.jclouds</groupId>
+            <artifactId>jclouds-compute</artifactId>
+            <version>${jclouds.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.jclouds.driver</groupId>
+            <artifactId>jclouds-slf4j</artifactId>
+            <version>${jclouds.version}</version>
+        </dependency>
+        <!-- 3rd party dependencies -->
+        <dependency>
+            <groupId>ch.qos.logback</groupId>
+            <artifactId>logback-classic</artifactId>
+            <version>1.0.13</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.jclouds.driver</groupId>
+            <artifactId>jclouds-slf4j</artifactId>
+            <version>${jclouds.version}</version>
+            <scope>compile</scope>
+        </dependency>
+
+    </dependencies>
+    <build>
+        <plugins>
+            <plugin>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <version>3.1</version>
+                <configuration>
+                    <encoding>${project.build.sourceEncoding}</encoding>
+                    <source>1.7</source>
+                    <target>1.7</target>
+                </configuration>
+            </plugin>
+            <plugin>
+                <artifactId>maven-assembly-plugin</artifactId>
+                <version>2.2.1</version>
+                <configuration>
+                    <descriptorRefs>
+                        <descriptorRef>jar-with-dependencies</descriptorRef>
+                    </descriptorRefs>
+                </configuration>
+                <executions>
+                    <execution>
+                        <id>make-assembly</id>
+                        <phase>package</phase>
+                        <goals>
+                            <goal>single</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+</project>
\ No newline at end of file
diff --git a/dimensiondata/src/main/java/org/jclouds/examples/dimensiondata/cloudcontrol/DeleteServerVlanAndNetworkDomain.java b/dimensiondata/src/main/java/org/jclouds/examples/dimensiondata/cloudcontrol/DeleteServerVlanAndNetworkDomain.java
new file mode 100644
index 0000000..8260277
--- /dev/null
+++ b/dimensiondata/src/main/java/org/jclouds/examples/dimensiondata/cloudcontrol/DeleteServerVlanAndNetworkDomain.java
@@ -0,0 +1,207 @@
+/*
+ * 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.examples.dimensiondata.cloudcontrol;
+
+import com.google.common.base.Optional;
+import com.google.common.base.Predicate;
+import com.google.common.collect.ImmutableSet;
+import com.google.inject.Injector;
+import org.jclouds.ContextBuilder;
+import org.jclouds.dimensiondata.cloudcontrol.DimensionDataCloudControlApi;
+import org.jclouds.dimensiondata.cloudcontrol.domain.Server;
+import org.jclouds.dimensiondata.cloudcontrol.domain.TagKey;
+import org.jclouds.dimensiondata.cloudcontrol.domain.Vlan;
+import org.jclouds.dimensiondata.cloudcontrol.options.DatacenterIdListFilters;
+import org.jclouds.logging.slf4j.config.SLF4JLoggingModule;
+import org.jclouds.rest.ApiContext;
+
+import static org.jclouds.examples.dimensiondata.cloudcontrol.WaitForUtils.*;
+
+/**
+ * This class will attempt to delete the assets created in org.jclouds.examples.dimensiondata.cloudcontrol.DeployNetworkDomainVlanAndServer:
+ * <ul>
+ * <li>Server</li>
+ * <li>Vlan</li>
+ * <li>Network Domain</li>
+ * <li>Tag Key</li>
+ * </ul>
+ */
+public class DeleteServerVlanAndNetworkDomain
+{
+    private static final String ZONE = System.getProperty("jclouds.zone", "AU9");
+    private static final String DIMENSIONDATA_CLOUDCONTROL_PROVIDER = "dimensiondata-cloudcontrol";
+
+    public static void main(String[] args)
+    {
+        /*
+         * Build an instance of the Dimension DataCloud Control Provider using the endpoint provided.
+         * Typically the endpoint will be of the form https://api-GEO.dimensiondata.com/caas
+         * We also need to provide authenticate details, a username and password.
+         *
+         * Internally the Dimension Data CloudControl Provider will use the org.jclouds.dimensiondata.cloudcontrol.features.AccountApi
+         * to lookup the organization identifier so that it is used as part of the requests.
+         *
+         */
+        String endpoint = args[0];
+        String username = args[1];
+        String password = args[2];
+
+        try (ApiContext<DimensionDataCloudControlApi> ctx = ContextBuilder.newBuilder(DIMENSIONDATA_CLOUDCONTROL_PROVIDER)
+                .endpoint(endpoint)
+                .credentials(username, password)
+                .modules(ImmutableSet.of(new SLF4JLoggingModule()))
+                .build())
+        {
+            /*
+             * Retrieve the Guice injector from the context.
+             * We will use this for retrieving the some Predicates that are used by the following operations.
+             */
+            Injector injector = ctx.utils().injector();
+            DimensionDataCloudControlApi api = ctx.getApi();
+
+            /*
+             * Referencing the asset created in org.jclouds.examples.dimensiondata.cloudcontrol.DeployNetworkDomainVlanAndServer
+             */
+            final String networkDomainName = "jclouds-example";
+            String networkDomainId = getNetworkDomainId(api, networkDomainName);
+            final String serverName = "jclouds-server";
+            final String vlanName = "jclouds-example-vlan";
+
+            deleteServer(api, injector, serverName);
+            deleteVlan(api, injector, vlanName, networkDomainId);
+            deleteNetworkDomain(api, injector, networkDomainId);
+            deleteTagKey(api, "jclouds");
+        }
+    }
+
+    private static void deleteTagKey(DimensionDataCloudControlApi api, final String tagkeyName)
+    {
+        /*
+         * Find the Tag Key and Delete using the id.
+         */
+        Optional<TagKey> tagKeyOptional = api.getTagApi().listTagKeys().concat().firstMatch(new Predicate<TagKey>()
+        {
+            @Override
+            public boolean apply(TagKey input)
+            {
+                return input.name().equals(tagkeyName);
+            }
+        });
+        if (tagKeyOptional.isPresent())
+        {
+            api.getTagApi().deleteTagKey(tagKeyOptional.get().id());
+        }
+    }
+
+    private static String getNetworkDomainId(DimensionDataCloudControlApi api, final String networkDomainName)
+    {
+        /*
+         * Find the Network Domain that was deployed by doing a filtered lookup using the datacenter and the network domain name.
+         */
+        return api.getNetworkApi().listNetworkDomainsWithDatacenterIdAndName(ZONE, networkDomainName).concat().toList().get(0).id();
+    }
+
+    private static void deleteVlan(DimensionDataCloudControlApi api, Injector injector, final String vlanName, String networkDomainId)
+    {
+        /*
+         * Find the Vlan that was deployed by listing all Vlans for the Network Domain and filtering by name
+         */
+        Optional<Vlan> vlanOptional = api.getNetworkApi().listVlans(networkDomainId).concat().firstMatch(new Predicate<Vlan>()
+        {
+            @Override
+            public boolean apply(Vlan input)
+            {
+                return input.name().equals(vlanName);
+            }
+        });
+        if (vlanOptional.isPresent())
+        {
+            Vlan vlan = vlanOptional.get();
+
+            /*
+             * Delete the Vlan using the id.
+             */
+            api.getNetworkApi().deleteVlan(vlan.id());
+
+            /*
+             * A Vlan delete is an asynchronous process. We need to wait for it to complete. The Dimension Data provider
+             * has built in predicates that will block execution and check that the Vlan is not found.
+             */
+            waitForDeleteVlan(injector, vlan);
+        }
+    }
+
+    private static void deleteNetworkDomain(DimensionDataCloudControlApi api, Injector injector, String networkDomainId)
+    {
+        /*
+         * Network Domain is deleted using the id.
+         */
+        api.getNetworkApi().deleteNetworkDomain(networkDomainId);
+
+        /*
+         * A Network Domain delete is an asynchronous process. We need to wait for it to complete. The Dimension Data provider
+         * has built in predicates that will block execution and check that the Network Domain is not found.
+         */
+        waitForDeleteNetworkDomain(injector, networkDomainId);
+    }
+
+    private static void deleteServer(DimensionDataCloudControlApi api, Injector injector, final String serverName)
+    {
+        /*
+         * We list all servers known to this organisation for the datacenter we are operating on. We filter the one that matches the server name we used to create it.
+         */
+        Optional<Server> serverOptional = api.getServerApi().listServers(DatacenterIdListFilters.Builder.datacenterId(ZONE)).firstMatch(new Predicate<Server>()
+        {
+            @Override
+            public boolean apply(Server input)
+            {
+                return input.name().equals(serverName);
+            }
+        });
+
+        if (serverOptional.isPresent())
+        {
+            Server server = serverOptional.get();
+            if (server.started())
+            {
+                /*
+                 * A Server must not be started in order to delete it. We call the shutdown server operation.
+                 */
+                api.getServerApi().shutdownServer(server.id());
+
+                /*
+                 * A Shutdown Server operation is an asynchronous process. We need to wait for it to complete. The Dimension Data provider
+                 * has built in predicates that will block execution and check that the Server is shutdown.
+                 */
+                waitForServerStopped(injector, server);
+            }
+
+            /*
+             * Server is deleted using the id.
+             */
+            api.getServerApi().deleteServer(server.id());
+
+            /*
+             * A Server delete is an asynchronous process. We need to wait for it to complete. The Dimension Data provider
+             * has built in predicates that will block execution and check that the Server is not found.
+             */
+            waitForServerDeleted(injector, server);
+
+        }
+    }
+
+}
diff --git a/dimensiondata/src/main/java/org/jclouds/examples/dimensiondata/cloudcontrol/DeployNetworkDomainVlanAndServer.java b/dimensiondata/src/main/java/org/jclouds/examples/dimensiondata/cloudcontrol/DeployNetworkDomainVlanAndServer.java
new file mode 100644
index 0000000..f6521e4
--- /dev/null
+++ b/dimensiondata/src/main/java/org/jclouds/examples/dimensiondata/cloudcontrol/DeployNetworkDomainVlanAndServer.java
@@ -0,0 +1,190 @@
+/*
+ * 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.examples.dimensiondata.cloudcontrol;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Lists;
+import com.google.inject.Injector;
+import org.jclouds.ContextBuilder;
+import org.jclouds.dimensiondata.cloudcontrol.DimensionDataCloudControlApi;
+import org.jclouds.dimensiondata.cloudcontrol.domain.Disk;
+import org.jclouds.dimensiondata.cloudcontrol.domain.NIC;
+import org.jclouds.dimensiondata.cloudcontrol.domain.NetworkInfo;
+import org.jclouds.dimensiondata.cloudcontrol.domain.TagInfo;
+import org.jclouds.dimensiondata.cloudcontrol.options.DatacenterIdListFilters;
+import org.jclouds.logging.slf4j.config.SLF4JLoggingModule;
+import org.jclouds.rest.ApiContext;
+
+import java.util.Collections;
+import java.util.List;
+
+import static org.jclouds.examples.dimensiondata.cloudcontrol.WaitForUtils.*;
+
+/**
+ * This class will attempt to Deploy:
+ * <ul>
+ * <li>Network Domain</li>
+ * <li>Vlan</li>
+ * <li>Server</li>cd ..
+ * </ul>
+ * <p>
+ * For each of these deployed assets we will tag them so that we know they were created by jclouds.
+ */
+public class DeployNetworkDomainVlanAndServer
+{
+
+    private static final String ZONE = System.getProperty("jclouds.zone", "AU9");
+    private static final String DIMENSIONDATA_CLOUDCONTROL_PROVIDER = "dimensiondata-cloudcontrol";
+
+    public static void main(String[] args)
+    {
+        String endpoint = args[0];
+        String username = args[1];
+        String password = args[2];
+        /*
+         * Build an instance of the Dimension DataCloud Control Provider using the endpoint provided.
+         * Typically the endpoint will be of the form https://api-GEO.dimensiondata.com/caas
+         * We also need to provide authenticate details, a username and password.
+         *
+         * Internally the Dimension Data CloudControl Provider will use the org.jclouds.dimensiondata.cloudcontrol.features.AccountApi
+         * to lookup the organization identifier so that it is used as part of the requests.
+         *
+         */
+        try (ApiContext<DimensionDataCloudControlApi> ctx = ContextBuilder.newBuilder(DIMENSIONDATA_CLOUDCONTROL_PROVIDER)
+                .endpoint(endpoint)
+                .credentials(username, password)
+                .modules(ImmutableSet.of(new SLF4JLoggingModule()))
+                .build())
+        {
+            /*
+             * Retrieve the Guice injector from the context.
+             * We will use this for retrieving the some Predicates that are used by the following operations.
+             */
+            Injector injector = ctx.utils().injector();
+            DimensionDataCloudControlApi api = ctx.getApi();
+
+            /*
+             * Create a tag key. We will use this to tag the assets that we create.
+             */
+            String tagKeyId = api.getTagApi().createTagKey("jclouds", "owner of the asset", true, false);
+
+            String networkDomainId = deployNetworkDomain(api, injector, tagKeyId);
+            String vlanId = deployVlan(api, injector, networkDomainId, tagKeyId);
+
+            deployServer(api, injector, networkDomainId, vlanId, tagKeyId);
+        }
+
+    }
+
+    private static void deployServer(DimensionDataCloudControlApi api, Injector injector, String
+            networkDomainId, String vlanId, String tagKeyId)
+    {
+        /*
+         * The server we deploy will use a pre-configured image.
+         *
+         * In Dimension Data Cloud Control we support OS Images and
+         * Customer Images (user created using the org.jclouds.dimensiondata.cloudcontrol.features.ServerApi.cloneServer operation)
+         */
+        String imageId = getOsImage(api);
+
+        /*
+         * The Server that gets deployed will have some network configuration. It gets assigned to the Vlan that was created previously.
+         */
+        NetworkInfo networkInfo = NetworkInfo
+                .create(networkDomainId, NIC.builder().vlanId(vlanId).build(), Lists.<NIC>newArrayList());
+        /*
+         * The Server that gets deployed will have some additional disk configuration.
+         */
+        List<Disk> disks = ImmutableList.of(Disk.builder().scsiId(0).speed("STANDARD").build());
+
+        /*
+         * The Server is deployed using the OS Image we selected,
+         * a flag to signal if we want it started or not, an admin pass and the additional configuration we built.
+         */
+        String serverId = api.getServerApi()
+                .deployServer("jclouds-server", imageId, true, networkInfo, "P$$ssWwrrdGoDd!", disks, null);
+
+        /*
+         * A Server deployment is an asynchronous process. We need to wait for it to complete. The Dimension Data provider
+         * has built in predicates that will block execution and check that the Server's State has moved from PENDING_ADD to NORMAL.
+         */
+        waitForServerStartedAndNormal(injector, serverId);
+
+        /*
+         * Apply a Tag to the Server. We use AssetType SERVER.
+         * We pass in the tagKeyId and a value that we want to associate, in this case jclouds.
+         */
+        api.getTagApi().applyTags(serverId, "SERVER", Collections.singletonList(TagInfo.create(tagKeyId, "jclouds")));
+    }
+
+    private static String getOsImage(DimensionDataCloudControlApi api)
+    {
+        /*
+         * We list available OS Images filtering on the Region (Datacenter) we wish to operate on.
+         */
+        return api.getServerImageApi().listOsImages(DatacenterIdListFilters.Builder.datacenterId(ZONE)).iterator().next().id();
+    }
+
+    private static String deployNetworkDomain(DimensionDataCloudControlApi api, Injector injector, String tagKeyId)
+    {
+
+        /*
+         * Deploy Network Domain to the Region we wish to operate on. The response from this API is the Network Domain Identifier.
+         */
+        String networkDomainId = api.getNetworkApi().deployNetworkDomain(ZONE, "jclouds-example", "jclouds-example", "ESSENTIALS");
+
+        /*
+         * A Network Domain deployment is an asynchronous process. We need to wait for it to complete. The Dimension Data provider
+         * has built in predicates that will block execution and check that the Network Domain's State has moved from PENDING_ADD to NORMAL.
+         * We pass the Network Domain Identifier we wish to check the state of.
+         */
+        waitForNetworkDomainNormal(injector, networkDomainId);
+
+        /*
+         * Apply a Tag to the Network Domain. We use AssetType NETWORK_DOMAIN.
+         * We pass in the tagKeyId and a value that we want to associate, in this case jclouds.
+         */
+        api.getTagApi().applyTags(networkDomainId, "NETWORK_DOMAIN", Collections.singletonList(TagInfo.create(tagKeyId, "jclouds")));
+        return networkDomainId;
+    }
+
+    private static String deployVlan(DimensionDataCloudControlApi api, Injector injector, String
+            networkDomainId, String tagKeyId)
+    {
+
+        /*
+         * Deploy the Vlan and associate it with the Network Domain that was previously created.
+         * The Vlan is deployed with a privateIpv4BaseAddress and privateIpv4PrefixSize
+         */
+        String vlanId = api.getNetworkApi().deployVlan(networkDomainId, "jclouds-example-vlan", "jclouds-example-vlan", "10.0.0.0", 24);
+
+        /*
+         * A Vlan deployment is an asynchronous process. We need to wait for it to complete. The Dimension Data provider
+         * has built in predicates that will block execution and check that the Vlan's State has moved from PENDING_ADD to NORMAL.
+         */
+        waitForVlanNormal(injector, vlanId);
+
+        /*
+         * Apply a Tag to the Vlan. We use AssetType VLAN.
+         * We pass in the tagKeyId and a value that we want to associate, in this case jclouds.
+         */
+        api.getTagApi().applyTags(vlanId, "VLAN", Collections.singletonList(TagInfo.create(tagKeyId, "jclouds")));
+        return vlanId;
+    }
+
+}
diff --git a/dimensiondata/src/main/java/org/jclouds/examples/dimensiondata/cloudcontrol/NetworkDomainTearDown.java b/dimensiondata/src/main/java/org/jclouds/examples/dimensiondata/cloudcontrol/NetworkDomainTearDown.java
new file mode 100644
index 0000000..8048f4c
--- /dev/null
+++ b/dimensiondata/src/main/java/org/jclouds/examples/dimensiondata/cloudcontrol/NetworkDomainTearDown.java
@@ -0,0 +1,200 @@
+/*
+ * 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.examples.dimensiondata.cloudcontrol;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
+import com.google.inject.Injector;
+import org.jclouds.ContextBuilder;
+import org.jclouds.dimensiondata.cloudcontrol.DimensionDataCloudControlApi;
+import org.jclouds.dimensiondata.cloudcontrol.domain.*;
+import org.jclouds.dimensiondata.cloudcontrol.options.DatacenterIdListFilters;
+import org.jclouds.logging.Logger;
+import org.jclouds.logging.slf4j.config.SLF4JLoggingModule;
+import org.jclouds.rest.ApiContext;
+
+import static org.jclouds.examples.dimensiondata.cloudcontrol.WaitForUtils.*;
+
+/**
+ * This example shows how a Network Domain and all of it's associated assets are removed.
+ * Takes 4 Program Arguments:
+ * <ul>
+ * <li>Endpoint URL</li>
+ * <li>Usernamme</li>
+ * <li>Password</li>
+ * <li>Network Domain Id</li>
+ * </ul>
+ */
+public class NetworkDomainTearDown
+{
+    private static final Logger logger = Logger.CONSOLE;
+
+    public static void main(String[] args)
+    {
+        String provider = "dimensiondata-cloudcontrol";
+        String endpoint = args[0];
+        String username = args[1];
+        String password = args[2];
+        String networkDomainId = args[3];
+
+        try (ApiContext<DimensionDataCloudControlApi> ctx = ContextBuilder.newBuilder(provider)
+                .endpoint(endpoint)
+                .credentials(username, password)
+                .modules(ImmutableSet.of(new SLF4JLoggingModule()))
+                .build())
+        {
+
+            /*
+             * Retrieve the Guice injector from the context.
+             * We will use this for retrieving the some Predicates that are used by the following operations.
+             */
+            Injector injector = ctx.utils().injector();
+            DimensionDataCloudControlApi api = ctx.getApi();
+
+
+            logger.info("Deleting resources for network domain %s", networkDomainId);
+            NetworkDomain networkDomain = api.getNetworkApi().getNetworkDomain(networkDomainId);
+            if (networkDomain == null)
+            {
+                logger.info("Network Domain with Id %s is not found", networkDomainId);
+                return;
+            }
+            if (networkDomain.state() != State.NORMAL)
+            {
+                logger.info("Network Domain with Id %s is not in a NORMAL state, cannot delete", networkDomain.id());
+                return;
+            }
+
+            String datacenterId = networkDomain.datacenterId();
+
+            removePublicIpBlocks(networkDomainId, api);
+
+            deleteNatRules(networkDomainId, api);
+
+            deleteFirewallRules(networkDomainId, api);
+
+            deleteServers(api, injector, datacenterId);
+
+            ImmutableList<Server> servers = api.getServerApi().listServers().concat().toList();
+            if (!servers.isEmpty())
+            {
+                logger.info("Could not delete all Servers. Servers not deleted:");
+                for (Server server : servers)
+                {
+                    logger.info("Id %s, Name %s, State, %s", server.id(), server.name(), server.state());
+                }
+                return;
+            }
+            deleteVlans(api, injector, networkDomain);
+
+            deleteNetworkDomain(networkDomainId, api, injector);
+        }
+    }
+
+    private static void removePublicIpBlocks(String networkDomainId, DimensionDataCloudControlApi api)
+    {
+        for (PublicIpBlock publicIpBlock : api.getNetworkApi().listPublicIPv4AddressBlocks(networkDomainId).concat().toList())
+        {
+            logger.info("Deleting PublicIpBlock with Id %s", publicIpBlock.id());
+            api.getNetworkApi().removePublicIpBlock(publicIpBlock.id());
+        }
+    }
+
+    private static void deleteFirewallRules(String networkDomainId, DimensionDataCloudControlApi api)
+    {
+        for (FirewallRule firewallRule : api.getNetworkApi().listFirewallRules(networkDomainId).concat().toList())
+        {
+            if (firewallRule.ruleType().equals("CLIENT_RULE"))
+            {
+                logger.info("Deleting FirewallRule with Id %s", firewallRule.id());
+                api.getNetworkApi().deleteFirewallRule(firewallRule.id());
+            }
+        }
+    }
+
+    private static void deleteNatRules(String networkDomainId, DimensionDataCloudControlApi api)
+    {
+        for (NatRule natRule : api.getNetworkApi().listNatRules(networkDomainId).concat().toList())
+        {
+            logger.info("Deleting NatRule with Id %s", natRule.id());
+            api.getNetworkApi().deleteNatRule(natRule.id());
+        }
+    }
+
+    private static void deleteNetworkDomain(String networkDomainId, DimensionDataCloudControlApi api, Injector injector)
+    {
+        logger.info("Deleting Network Domain with Id %s", networkDomainId);
+        api.getNetworkApi().deleteNetworkDomain(networkDomainId);
+        waitForDeleteNetworkDomain(injector, networkDomainId);
+    }
+
+    private static void deleteVlans(DimensionDataCloudControlApi api, Injector injector, NetworkDomain networkDomain)
+    {
+        for (Vlan vlan : api.getNetworkApi().listVlans(networkDomain.id()).concat().toList())
+        {
+            try
+            {
+                if (vlan.state() != State.NORMAL)
+                {
+                    logger.info("Vlan with Id %s is not in a NORMAL state, cannot delete", vlan.id());
+                    continue;
+                }
+                logger.info("Deleting Vlan with Id %s", vlan.id());
+                api.getNetworkApi().deleteVlan(vlan.id());
+                waitForDeleteVlan(injector, vlan);
+            }
+            catch (Exception e)
+            {
+                logger.error("Unable to delete Vlan with Id %s due to: %s", vlan.id(), e.getMessage());
+            }
+        }
+    }
+
+    private static void deleteServers(DimensionDataCloudControlApi api, Injector injector, String datacenterId)
+    {
+        for (Server server : api.getServerApi().listServers(DatacenterIdListFilters.Builder.datacenterId(datacenterId)))
+        {
+            try
+            {
+                if (server.state() == State.FAILED_ADD)
+                {
+                    logger.info("Server with Id %s is not in a FAILED_ADD state, manually run Clean Server operation.", server.id());
+                    continue;
+                }
+                if (server.state() != State.NORMAL)
+                {
+                    logger.info("Server with Id %s is not in a NORMAL state, current state %s - cannot delete", server.id(), server.state());
+                    continue;
+                }
+                if (server.started())
+                {
+                    logger.info("Shutting down Server with Id %s", server.id());
+                    api.getServerApi().shutdownServer(server.id());
+                    waitForServerStopped(injector, server);
+                }
+                logger.info("Deleting Server with Id %s", server.id());
+                api.getServerApi().deleteServer(server.id());
+                waitForServerDeleted(injector, server);
+            }
+            catch (Exception e)
+            {
+                logger.error("Unable to Delete Server with Id %s due to: %s", server.id(), e.getMessage());
+            }
+        }
+    }
+
+}
diff --git a/dimensiondata/src/main/java/org/jclouds/examples/dimensiondata/cloudcontrol/WaitForUtils.java b/dimensiondata/src/main/java/org/jclouds/examples/dimensiondata/cloudcontrol/WaitForUtils.java
new file mode 100644
index 0000000..53bae18
--- /dev/null
+++ b/dimensiondata/src/main/java/org/jclouds/examples/dimensiondata/cloudcontrol/WaitForUtils.java
@@ -0,0 +1,108 @@
+/*
+ * 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.examples.dimensiondata.cloudcontrol;
+
+import com.google.common.base.Predicate;
+import com.google.inject.Injector;
+import com.google.inject.Key;
+import com.google.inject.TypeLiteral;
+import com.google.inject.name.Names;
+import org.jclouds.dimensiondata.cloudcontrol.domain.Server;
+import org.jclouds.dimensiondata.cloudcontrol.domain.Vlan;
+
+public class WaitForUtils
+{
+
+    private static final String SERVER_STARTED_PREDICATE = "SERVER_STARTED_PREDICATE";
+    private static final String SERVER_NORMAL_PREDICATE = "SERVER_NORMAL_PREDICATE";
+    private static final String NETWORK_DOMAIN_NORMAL_PREDICATE = "NETWORK_DOMAIN_NORMAL_PREDICATE";
+    private static final String VLAN_NORMAL_PREDICATE = "VLAN_NORMAL_PREDICATE";
+    private static final String SERVER_DELETED_PREDICATE = "SERVER_DELETED_PREDICATE";
+    private static final String NETWORK_DOMAIN_DELETED_PREDICATE = "NETWORK_DOMAIN_DELETED_PREDICATE";
+    private static final String VLAN_DELETED_PREDICATE = "VLAN_DELETED_PREDICATE";
+    private static final String SERVER_STOPPED_PREDICATE = "SERVER_STOPPED_PREDICATE";
+
+    static void waitForServerStopped(Injector injector, Server server)
+    {
+        Predicate<String> serverStoppedPredicate = injector.getInstance(Key.get(new TypeLiteral<Predicate<String>>()
+        {
+        }, Names.named(SERVER_STOPPED_PREDICATE)));
+
+        // Wait for Server to be STOPPED
+        serverStoppedPredicate.apply(server.id());
+    }
+
+    static void waitForDeleteVlan(Injector injector, Vlan vlan)
+    {
+        Predicate<String> vlanDeletedPredicate = injector.getInstance(Key.get(new TypeLiteral<Predicate<String>>()
+        {
+        }, Names.named(VLAN_DELETED_PREDICATE)));
+
+        // Wait for VLAN to be DELETED
+        vlanDeletedPredicate.apply(vlan.id());
+    }
+
+    static void waitForDeleteNetworkDomain(Injector injector, String networkDomainId)
+    {
+        Predicate<String> networkDomainDeletedPredicate = injector.getInstance(Key.get(new TypeLiteral<Predicate<String>>()
+        {
+        }, Names.named(NETWORK_DOMAIN_DELETED_PREDICATE)));
+
+        // Wait for NETWORK DOMAIN to be DELETED
+        networkDomainDeletedPredicate.apply(networkDomainId);
+    }
+
+    static void waitForServerDeleted(Injector injector, Server server)
+    {
+        Predicate<String> serverDeletedPredicate = injector.getInstance(Key.get(new TypeLiteral<Predicate<String>>()
+        {
+        }, Names.named(SERVER_DELETED_PREDICATE)));
+
+        // Wait for Server to be DELETED
+        serverDeletedPredicate.apply(server.id());
+    }
+
+    static void waitForServerStartedAndNormal(Injector injector, String serverId)
+    {
+        Predicate<String> serverStartedPredicate = injector.getInstance(Key.get(new TypeLiteral<Predicate<String>>()
+        {
+        }, Names.named(SERVER_STARTED_PREDICATE)));
+        Predicate<String> serverNormalPredicate = injector.getInstance(Key.get(new TypeLiteral<Predicate<String>>()
+        {
+        }, Names.named(SERVER_NORMAL_PREDICATE)));
+
+        // Wait for Server to be started and NORMAL
+        serverStartedPredicate.apply(serverId);
+        serverNormalPredicate.apply(serverId);
+    }
+
+    static void waitForNetworkDomainNormal(Injector injector, String networkDomainId)
+    {
+        Predicate<String> networkDomainNormalPredicate = injector.getInstance(Key.get(new TypeLiteral<Predicate<String>>()
+        {
+        }, Names.named(NETWORK_DOMAIN_NORMAL_PREDICATE)));
+        networkDomainNormalPredicate.apply(networkDomainId);
+    }
+
+    static void waitForVlanNormal(Injector injector, String vlanId)
+    {
+        Predicate<String> vlanNormalPredicate = injector.getInstance(Key.get(new TypeLiteral<Predicate<String>>()
+        {
+        }, Names.named(VLAN_NORMAL_PREDICATE)));
+        vlanNormalPredicate.apply(vlanId);
+    }
+}
diff --git a/dimensiondata/src/main/resources/logback.xml b/dimensiondata/src/main/resources/logback.xml
new file mode 100644
index 0000000..b869509
--- /dev/null
+++ b/dimensiondata/src/main/resources/logback.xml
@@ -0,0 +1,89 @@
+<?xml version="1.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.
+
+-->
+
+<configuration scan="false">
+    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
+        <encoder>
+          <pattern>-  %m%n</pattern>
+        </encoder>
+    </appender>
+
+    <appender name="FILE" class="ch.qos.logback.core.FileAppender">
+        <file>target/test-data/jclouds.log</file>
+
+        <encoder>
+            <Pattern>%d %-5p [%c] [%thread] %m%n</Pattern>
+        </encoder>
+    </appender>
+
+    <appender name="WIREFILE" class="ch.qos.logback.core.FileAppender">
+        <file>target/test-data/jclouds-wire.log</file>
+
+        <encoder>
+            <Pattern>%d %-5p [%c] [%thread] %m%n</Pattern>
+        </encoder>
+    </appender>
+
+    <appender name="COMPUTEFILE" class="ch.qos.logback.core.FileAppender">
+        <file>target/test-data/jclouds-compute.log</file>
+
+        <encoder>
+            <Pattern>%d %-5p [%c] [%thread] %m%n</Pattern>
+        </encoder>
+    </appender>
+    
+    <appender name="SSHFILE" class="ch.qos.logback.core.FileAppender">
+        <file>target/test-data/jclouds-ssh.log</file>
+
+        <encoder>
+            <Pattern>%d %-5p [%c] [%thread] %m%n</Pattern>
+        </encoder>
+    </appender>
+
+    <root>
+        <level value="warn" />
+    </root>
+
+    <logger name="org.jclouds">
+        <level value="DEBUG" />
+        <appender-ref ref="FILE" />
+    </logger>
+
+    <logger name="jclouds.wire">
+        <level value="DEBUG" />
+        <appender-ref ref="STDOUT" />
+    </logger>
+
+    <logger name="jclouds.headers">
+        <level value="DEBUG" />
+        <appender-ref ref="STDOUT" />
+    </logger>
+
+    <logger name="jclouds.compute">
+        <level value="DEBUG" />
+        <appender-ref ref="COMPUTEFILE" />
+    </logger>
+    
+    <logger name="jclouds.ssh">
+        <level value="DEBUG" />
+        <appender-ref ref="SSHFILE" />
+    </logger>
+
+</configuration>
diff --git a/pom.xml b/pom.xml
index b2aa183..41f2eb8 100644
--- a/pom.xml
+++ b/pom.xml
@@ -69,6 +69,7 @@
     <module>google-lb</module>
     <module>openstack</module>
     <module>rackspace</module>
+    <module>dimensiondata</module>
   </modules>
 
   <build>