You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@libcloud.apache.org by to...@apache.org on 2015/08/30 14:32:50 UTC

[02/21] libcloud git commit: [LIBCLOUD-736] Updated driver to use 2.0 for all new API calls, start/stop/restart server. list servers using new API, updated extra calls for VLAN and network domain. Fixed up unit tests and added new fixtures

[LIBCLOUD-736] Updated driver to use 2.0 for all new API calls, start/stop/restart server. list servers using new API, updated extra calls for VLAN and network domain. Fixed up unit tests and added new fixtures


Project: http://git-wip-us.apache.org/repos/asf/libcloud/repo
Commit: http://git-wip-us.apache.org/repos/asf/libcloud/commit/0ba9ae48
Tree: http://git-wip-us.apache.org/repos/asf/libcloud/tree/0ba9ae48
Diff: http://git-wip-us.apache.org/repos/asf/libcloud/diff/0ba9ae48

Branch: refs/heads/trunk
Commit: 0ba9ae48c6aed9d94a0cf1b0e57c995e6ca71f37
Parents: 9a9fafe
Author: Anthony Shaw <an...@gmail.com>
Authored: Tue Aug 25 16:42:13 2015 +1000
Committer: Anthony Shaw <an...@gmail.com>
Committed: Tue Aug 25 16:42:13 2015 +1000

----------------------------------------------------------------------
 libcloud/compute/drivers/dimensiondata.py       | 312 ++++++++++++++-----
 ...c_8dabe5a7d0e4_infrastructure_datacenter.xml |  44 +++
 ..._9cbc_8dabe5a7d0e4_network_networkDomain.xml |  13 +
 ...2745_4d8a_9cbc_8dabe5a7d0e4_network_vlan.xml |  17 +
 ...8a_9cbc_8dabe5a7d0e4_server_deleteServer.xml |   9 +
 ...5a7d0e4_server_deleteServer_RESOURCEBUSY.xml |   8 +
 ..._9cbc_8dabe5a7d0e4_server_powerOffServer.xml |   8 +
 ...5a7d0e4_server_powerOffServer_INPROGRESS.xml |   8 +
 ...8a_9cbc_8dabe5a7d0e4_server_rebootServer.xml |   8 +
 ...5a7d0e4_server_rebootServer_RESOURCEBUSY.xml |   7 +
 ...d8a_9cbc_8dabe5a7d0e4_server_resetServer.xml |   8 +
 ...745_4d8a_9cbc_8dabe5a7d0e4_server_server.xml |  59 ++++
 ..._9cbc_8dabe5a7d0e4_server_shutdownServer.xml |   8 +
 ...5a7d0e4_server_shutdownServer_INPROGRESS.xml |   8 +
 ...d8a_9cbc_8dabe5a7d0e4_server_startServer.xml |   8 +
 ...abe5a7d0e4_server_startServer_INPROGRESS.xml |   8 +
 ...8a_9cbc_8dabe5a7d0e4_networkWithLocation.xml |   2 +-
 .../dimensiondata/oec_0_9_base_image.xml        | 140 +--------
 libcloud/test/compute/test_dimensiondata.py     | 120 ++++++-
 19 files changed, 583 insertions(+), 212 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/libcloud/blob/0ba9ae48/libcloud/compute/drivers/dimensiondata.py
----------------------------------------------------------------------
diff --git a/libcloud/compute/drivers/dimensiondata.py b/libcloud/compute/drivers/dimensiondata.py
index 0a95255..9819111 100644
--- a/libcloud/compute/drivers/dimensiondata.py
+++ b/libcloud/compute/drivers/dimensiondata.py
@@ -30,7 +30,7 @@ from libcloud.compute.base import NodeDriver, Node
 from libcloud.compute.base import NodeSize, NodeImage, NodeLocation
 from libcloud.common.types import LibcloudError, InvalidCredsError
 from libcloud.common.base import ConnectionUserAndKey, XmlResponse
-from libcloud.utils.xml import fixxpath, findtext, findall
+from libcloud.utils.xml import fixxpath, findtext, findall, findattr
 from libcloud.compute.types import NodeState, Provider
 
 # Roadmap / TODO:
@@ -52,6 +52,9 @@ GENERAL_NS = NAMESPACE_BASE + "/general"
 IPPLAN_NS = NAMESPACE_BASE + "/ipplan"
 WHITELABEL_NS = NAMESPACE_BASE + "/whitelabel"
 
+# API 2.0 Namespaces and URNs
+TYPES_URN = "urn:didata.com:api:cloud:types"
+
 # API end-points
 API_ENDPOINTS = {
     'dd-na': {
@@ -104,9 +107,10 @@ class DimensionDataResponse(XmlResponse):
 
         body = self.parse_body()
 
+        # TODO: The path is not fixed as server. 
         if self.status == httplib.BAD_REQUEST:
-            code = findtext(body, 'resultCode', SERVER_NS)
-            message = findtext(body, 'resultDetail', SERVER_NS)
+            code = findtext(body, 'responseCode', SERVER_NS)
+            message = findtext(body, 'message', SERVER_NS)
             raise DimensionDataAPIException(code,
                                             message,
                                             driver=DimensionDataNodeDriver)
@@ -133,8 +137,11 @@ class DimensionDataConnection(ConnectionUserAndKey):
     Connection class for the DimensionData driver
     """
 
-    api_path = '/oec'
-    api_version = '0.9'
+    api_path_version_1 = '/oec'
+    api_path_version_2 = '/caas'
+    api_version_1 = '0.9'
+    api_version_2 = '2.0'
+    
     _orgId = None
     responseCls = DimensionDataResponse
 
@@ -159,31 +166,58 @@ class DimensionDataConnection(ConnectionUserAndKey):
                                                  self.key))).decode('utf-8'))
         return headers
 
-    def request(self, action, params=None, data='',
+    def request_api_1(self, action, params=None, data='',
                 headers=None, method='GET'):
-        action = "%s/%s/%s" % (self.api_path, self.api_version, action)
+        action = "%s/%s/%s" % (self.api_path_version_1, self.api_version_1, action)
 
         return super(DimensionDataConnection, self).request(
             action=action,
             params=params, data=data,
             method=method, headers=headers)
+    
+    def request_api_2(self, path, action, params=None, data='',
+                headers=None, method='GET'):
+        action = "%s/%s/%s/%s" % (self.api_path_version_2, self.api_version_2, path, action)
 
-    def request_with_orgId(self, action, params=None, data='',
+        return super(DimensionDataConnection, self).request(
+            action=action,
+            params=params, data=data,
+            method=method, headers=headers)
+
+    def request_with_orgId_api_1(self, action, params=None, data='',
+                           headers=None, method='GET'):
+        action = "%s/%s" % (self.get_resource_path_api_1(), action)
+
+        return super(DimensionDataConnection, self).request(
+            action=action,
+            params=params, data=data,
+            method=method, headers=headers)
+    
+    def request_with_orgId_api_2(self, action, params=None, data='',
                            headers=None, method='GET'):
-        action = "%s/%s" % (self.get_resource_path(), action)
+        action = "%s/%s" % (self.get_resource_path_api_2(), action)
 
         return super(DimensionDataConnection, self).request(
             action=action,
             params=params, data=data,
             method=method, headers=headers)
 
-    def get_resource_path(self):
+    def get_resource_path_api_1(self):
         """
         This method returns a resource path which is necessary for referencing
         resources that require a full path instead of just an ID, such as
         networks, and customer snapshots.
         """
-        return ("%s/%s/%s" % (self.api_path, self.api_version,
+        return ("%s/%s/%s" % (self.api_path_version_1, self.api_version_1,
+                              self._get_orgId()))
+
+    def get_resource_path_api_2(self):
+        """
+        This method returns a resource path which is necessary for referencing
+        resources that require a full path instead of just an ID, such as
+        networks, and customer snapshots.
+        """
+        return ("%s/%s/%s" % (self.api_path_version_2, self.api_version_2,
                               self._get_orgId()))
 
     def _get_orgId(self):
@@ -193,7 +227,7 @@ class DimensionDataConnection(ConnectionUserAndKey):
         of the other API functions
         """
         if self._orgId is None:
-            body = self.request('myaccount').object
+            body = self.request_api_1('myaccount').object
             self._orgId = findtext(body, 'orgId', DIRECTORY_NS)
         return self._orgId
 
@@ -250,6 +284,39 @@ class DimensionDataNetwork(object):
                 % (self.id, self.name, self.description, self.location,
                    self.private_net, self.multicast))
 
+class DimensionDataNetworkDomain(object):
+    """
+    DimensionData network domain with location.
+    """
+
+    def __init__(self, id, name, description, location, status):
+        self.id = str(id)
+        self.name = name
+        self.description = description
+        self.location = location
+        self.status = status
+
+    def __repr__(self):
+        return (('<DimensionDataNetworkDomain: id=%s, name=%s, description=%s, '
+                 'location=%s, status=%s>')
+                % (self.id, self.name, self.description, self.location, self.status))
+
+class DimensionDataVlan(object):
+    """
+    DimensionData VLAN.
+    """
+
+    def __init__(self, id, name, description, location, status):
+        self.id = str(id)
+        self.name = name
+        self.location = location
+        self.description = description
+        self.status = status
+
+    def __repr__(self):
+        return (('<DimensionDataNetworkDomain: id=%s, name=%s, description=%s, '
+                 'location=%s, status=%s>')
+                % (self.id, self.name, self.description, self.location, self.status))
 
 class DimensionDataNodeDriver(NodeDriver):
     """
@@ -332,14 +399,14 @@ class DimensionDataNodeDriver(NodeDriver):
 
         if not isinstance(ex_network, DimensionDataNetwork):
             raise ValueError('ex_network must be of DimensionDataNetwork type')
-        vlanResourcePath = "%s/%s" % (self.connection.get_resource_path(),
+        vlanResourcePath = "%s/%s" % (self.connection.get_resource_path_api_1(),
                                       ex_network.id)
 
         imageResourcePath = None
         if 'resourcePath' in image.extra:
             imageResourcePath = image.extra['resourcePath']
         else:
-            imageResourcePath = "%s/%s" % (self.connection.get_resource_path(),
+            imageResourcePath = "%s/%s" % (self.connection.get_resource_path_api_1(),
                                            image.id)
 
         server_elm = ET.Element('Server', {'xmlns': SERVER_NS})
@@ -350,7 +417,7 @@ class DimensionDataNodeDriver(NodeDriver):
         ET.SubElement(server_elm, "administratorPassword").text = password
         ET.SubElement(server_elm, "isStarted").text = str(ex_is_started)
 
-        self.connection.request_with_orgId('server',
+        self.connection.request_with_orgId_api_1('server',
                                            method='POST',
                                            data=ET.tostring(server_elm)).object
 
@@ -366,23 +433,23 @@ class DimensionDataNodeDriver(NodeDriver):
         return node
 
     def destroy_node(self, node):
-        body = self.connection.request_with_orgId(
-            'server/%s?delete' % (node.id)).object
-
-        result = findtext(body, 'result', GENERAL_NS)
-        return result == 'SUCCESS'
+        request_elm = ET.Element('deleteServer', {'xmlns': TYPES_URN, 'id': node.id})
+        body = self.connection.request_with_orgId_api_2(
+            'server/deleteServer', method='POST', data=ET.tostring(request_elm) ).object
+        result = findtext(body, 'responseCode', TYPES_URN)
+        return result == 'IN_PROGRESS'
 
     def reboot_node(self, node):
-        body = self.connection.request_with_orgId(
-            'server/%s?restart' % (node.id)).object
-        result = findtext(body, 'result', GENERAL_NS)
-        return result == 'SUCCESS'
+        request_elm = ET.Element('rebootServer', {'xmlns': TYPES_URN, 'id': node.id})
+        body = self.connection.request_with_orgId_api_2(
+            'server/rebootServer', method='POST', data=ET.tostring(request_elm) ).object
+        result = findtext(body, 'responseCode', TYPES_URN)
+        return result == 'IN_PROGRESS'
 
     def list_nodes(self):
         nodes = self._to_nodes(
-            self.connection.request_with_orgId('server/deployed').object)
-        nodes.extend(self._to_nodes(
-            self.connection.request_with_orgId('server/pendingDeploy').object))
+            self.connection.request_with_orgId_api_2('server/server').object)
+      
         return nodes
 
     def list_images(self, location=None):
@@ -394,9 +461,16 @@ class DimensionDataNodeDriver(NodeDriver):
         @inherits: :class:`NodeDriver.list_images`
         """
         return self._to_base_images(
-            self.connection.request('base/image').object)
+            self.connection.request_api_1('base/image').object)
 
     def list_sizes(self, location=None):
+        """
+        return a list of available sizes
+            Currently, the size of the node is dictated by the chosen OS base
+            image, they cannot be set explicitly.
+
+        @inherits: :class:`NodeDriver.list_sizes`
+        """
         return [
             NodeSize(id=1,
                      name="default",
@@ -415,7 +489,7 @@ class DimensionDataNodeDriver(NodeDriver):
         @inherits: :class:`NodeDriver.list_locations`
         """
         return self._to_locations(
-            self.connection.request_with_orgId('datacenter').object)
+            self.connection.request_with_orgId_api_2('infrastructure/datacenter').object)
 
     def list_networks(self, location=None):
         """
@@ -430,7 +504,7 @@ class DimensionDataNodeDriver(NodeDriver):
         :rtype: ``list`` of :class:`DimensionDataNetwork`
         """
         return self._to_networks(
-            self.connection.request_with_orgId('networkWithLocation').object)
+            self.connection.request_with_orgId_api_1('networkWithLocation').object)
 
     def _to_base_images(self, object):
         images = []
@@ -476,10 +550,11 @@ class DimensionDataNodeDriver(NodeDriver):
 
         :rtype: ``bool``
         """
-        body = self.connection.request_with_orgId(
-            'server/%s?start' % node.id).object
-        result = findtext(body, 'result', GENERAL_NS)
-        return result == 'SUCCESS'
+        request_elm = ET.Element('startServer', {'xmlns': TYPES_URN, 'id': node.id})
+        body = self.connection.request_with_orgId_api_2(
+            'server/startServer', method='POST', data=ET.tostring(request_elm) ).object
+        result = findtext(body, 'responseCode', TYPES_URN)
+        return result == 'IN_PROGRESS'
 
     def ex_shutdown_graceful(self, node):
         """
@@ -493,10 +568,11 @@ class DimensionDataNodeDriver(NodeDriver):
 
         :rtype: ``bool``
         """
-        body = self.connection.request_with_orgId(
-            'server/%s?shutdown' % (node.id)).object
-        result = findtext(body, 'result', GENERAL_NS)
-        return result == 'SUCCESS'
+        request_elm = ET.Element('shutdownServer', {'xmlns': TYPES_URN, 'id': node.id})
+        body = self.connection.request_with_orgId_api_2(
+            'server/shutdownServer', method='POST', data=ET.tostring(request_elm) ).object
+        result = findtext(body, 'responseCode', TYPES_URN)
+        return result == 'IN_PROGRESS'
 
     def ex_power_off(self, node):
         """
@@ -510,10 +586,29 @@ class DimensionDataNodeDriver(NodeDriver):
 
         :rtype: ``bool``
         """
-        body = self.connection.request_with_orgId(
-            'server/%s?poweroff' % node.id).object
-        result = findtext(body, 'result', GENERAL_NS)
-        return result == 'SUCCESS'
+        request_elm = ET.Element('powerOffServer', {'xmlns': TYPES_URN, 'id': node.id})
+        body = self.connection.request_with_orgId_api_2(
+            'server/powerOffServer', method='POST', data=ET.tostring(request_elm) ).object
+        result = findtext(body, 'responseCode', TYPES_URN)
+        return result == 'IN_PROGRESS'
+
+    def ex_reset(self, node):
+        """
+        This function will abruptly reset a server.  Unlike
+        reboot_node, success ensures the node will restart but some OS
+        and application configurations may be adversely affected by the
+        equivalent of pulling the power plug out of the machine.
+
+        :param      node: Node which should be used
+        :type       node: :class:`Node`
+
+        :rtype: ``bool``
+        """
+        request_elm = ET.Element('resetServer', {'xmlns': TYPES_URN, 'id': node.id})
+        body = self.connection.request_with_orgId_api_2(
+            'server/resetServer', method='POST', data=ET.tostring(request_elm) ).object
+        result = findtext(body, 'responseCode', TYPES_URN)
+        return result == 'IN_PROGRESS'
 
     def ex_list_networks(self):
         """
@@ -523,10 +618,33 @@ class DimensionDataNodeDriver(NodeDriver):
         :return: a list of DimensionDataNetwork objects
         :rtype: ``list`` of :class:`DimensionDataNetwork`
         """
-        response = self.connection.request_with_orgId('networkWithLocation') \
+        response = self.connection.request_with_orgId_api_1('networkWithLocation') \
                                   .object
         return self._to_networks(response)
 
+    def ex_list_network_domains(self):
+        """
+        List networks deployed across all data center locations for your
+        organization.  The response includes the location of each network.
+
+        :return: a list of DimensionDataNetwork objects
+        :rtype: ``list`` of :class:`DimensionDataNetwork`
+        """
+        response = self.connection.request_with_orgId_api_2('network/networkDomain') \
+                                  .object
+        return self._to_network_domains(response)
+
+    def ex_list_vlans(self):
+        """
+        List VLANs available in a given networkDomain
+
+        :return: a list of DimensionDataVlan objects
+        :rtype: ``list`` of :class:`DimensionDataVlan`
+        """
+        response = self.connection.request_with_orgId_api_2('network/vlan') \
+                                  .object
+        return self._to_vlans(response)
+
     def ex_get_location_by_id(self, id):
         """
         Get location by ID.
@@ -569,67 +687,107 @@ class DimensionDataNodeDriver(NodeDriver):
                                  NETWORK_NS),
             multicast=multicast,
             status=status)
+    
+    def _to_network_domains(self, object):
+        network_domains = []
+        for element in findall(object, 'networkDomain', TYPES_URN):
+            network_domains.append(self._to_network_domain(element))
+
+        return network_domains
+
+    def _to_network_domain(self, element):
+        status = self._to_status(element.find(fixxpath('state', TYPES_URN)))
+
+        location_id = element.get('datacenter')
+        location = self.ex_get_location_by_id(location_id)
+
+        return DimensionDataNetworkDomain(
+            id=element.get('id'),
+            name=findtext(element, 'name', TYPES_URN),
+            description=findtext(element, 'description',
+                                 TYPES_URN),
+            location=location,
+            status=status)
+
+    def _to_vlans(self, object):
+        vlans = []
+        for element in findall(object, 'vlan', TYPES_URN):
+            vlans.append(self._to_vlan(element))
+
+        return vlans
+
+    def _to_vlan(self, element):
+        status = self._to_status(element.find(fixxpath('state', TYPES_URN)))
+        
+        location_id = element.get('location')
+        location = self.ex_get_location_by_id(location_id)
+        
+        return DimensionDataVlan(
+            id=element.get('id'),
+            name=findtext(element, 'name', TYPES_URN),
+            description=findtext(element, 'description',
+                                 TYPES_URN),
+            location=location,
+            status=status)
 
     def _to_locations(self, object):
         locations = []
-        for element in object.findall(fixxpath('datacenter', DATACENTER_NS)):
+        for element in object.findall(fixxpath('datacenter', TYPES_URN)):
             locations.append(self._to_location(element))
 
         return locations
 
     def _to_location(self, element):
-        l = NodeLocation(id=findtext(element, 'location', DATACENTER_NS),
-                         name=findtext(element, 'displayName', DATACENTER_NS),
-                         country=findtext(element, 'country', DATACENTER_NS),
+        l = NodeLocation(id=element.get('id'),
+                         name=findtext(element, 'displayName', TYPES_URN),
+                         country=findtext(element, 'country', TYPES_URN),
                          driver=self)
         return l
 
     def _to_nodes(self, object):
-        node_elements = object.findall(fixxpath('DeployedServer', SERVER_NS))
-        node_elements.extend(object.findall(
-            fixxpath('PendingDeployServer', SERVER_NS)))
+        node_elements = object.findall(fixxpath('Server', TYPES_URN))
+
         return [self._to_node(el) for el in node_elements]
 
     def _to_node(self, element):
-        if findtext(element, 'isStarted', SERVER_NS) == 'true':
+        if findtext(element, 'started', TYPES_URN) == 'true':
             state = NodeState.RUNNING
         else:
             state = NodeState.TERMINATED
 
-        status = self._to_status(element.find(fixxpath('status', SERVER_NS)))
+        status = self._to_status(element.find(fixxpath('state', TYPES_URN)))
 
         extra = {
-            'description': findtext(element, 'description', SERVER_NS),
-            'sourceImageId': findtext(element, 'sourceImageId', SERVER_NS),
-            'networkId': findtext(element, 'networkId', SERVER_NS),
-            'machineName': findtext(element, 'machineName', SERVER_NS),
-            'deployedTime': findtext(element, 'deployedTime', SERVER_NS),
-            'cpuCount': findtext(element, 'machineSpecification/cpuCount',
-                                 SERVER_NS),
-            'memoryMb': findtext(element, 'machineSpecification/memoryMb',
-                                 SERVER_NS),
-            'osStorageGb': findtext(element,
-                                    'machineSpecification/osStorageGb',
-                                    SERVER_NS),
-            'additionalLocalStorageGb': findtext(
-                element, 'machineSpecification/additionalLocalStorageGb',
-                SERVER_NS),
-            'OS_type': findtext(element,
-                                'machineSpecification/operatingSystem/type',
-                                SERVER_NS),
-            'OS_displayName': findtext(
-                element, 'machineSpecification/operatingSystem/displayName',
-                SERVER_NS),
+            'description': findtext(element, 'description', TYPES_URN),
+            'sourceImageId': findtext(element, 'sourceImageId', TYPES_URN),
+            'networkId': findtext(element, 'networkId', TYPES_URN),
+            'networkDomainId': element.find(fixxpath('networkInfo', TYPES_URN))
+                                      .get('networkDomainId'),
+            'datacenterId': element.get('datacenterId'),
+            'deployedTime': findtext(element, 'createTime', TYPES_URN),
+            'cpuCount': int(findtext(element, 'cpuCount',
+                                 TYPES_URN)),
+            'memoryMb': int(findtext(element, 'memoryGb',
+                                 TYPES_URN)) * 1024,
+            'OS_id': element.find(fixxpath('operatingSystem', TYPES_URN))
+                                      .get('id'),
+            'OS_type': element.find(fixxpath('operatingSystem', TYPES_URN))
+                                      .get('family'),
+            'OS_displayName': element.find(fixxpath('operatingSystem', TYPES_URN))
+                                      .get('displayName'),
             'status': status,
         }
 
-        public_ip = findtext(element, 'publicIpAddress', SERVER_NS)
+        public_ip = findtext(element, 'publicIpAddress', TYPES_URN)
+
+        private_ip = findtext(element, 'networkInfo/primaryNic/privateIpv4',
+                              TYPES_URN)
 
-        n = Node(id=findtext(element, 'id', SERVER_NS),
-                 name=findtext(element, 'name', SERVER_NS),
+        n = Node(id=element.get('id'),
+                 name=findtext(element, 'name', TYPES_URN),
                  state=state,
                  public_ips=[public_ip] if public_ip is not None else [],
-                 private_ips=findtext(element, 'privateIpAddress', SERVER_NS),
+                 private_ips=[private_ip] if private_ip is not None else [],
                  driver=self.connection.driver,
                  extra=extra)
         return n

http://git-wip-us.apache.org/repos/asf/libcloud/blob/0ba9ae48/libcloud/test/compute/fixtures/dimensiondata/caas_2_0_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_infrastructure_datacenter.xml
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/dimensiondata/caas_2_0_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_infrastructure_datacenter.xml b/libcloud/test/compute/fixtures/dimensiondata/caas_2_0_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_infrastructure_datacenter.xml
new file mode 100644
index 0000000..66ae1db
--- /dev/null
+++ b/libcloud/test/compute/fixtures/dimensiondata/caas_2_0_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_infrastructure_datacenter.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<datacenters pageNumber="1" pageCount="1" totalCount="2" pageSize="50"
+xmlns="urn:didata.com:api:cloud:types">
+<datacenter id="NA10" type="MCP 2.0">
+<displayName>US - West</displayName>
+<city>Santa Clara</city>
+<state>California</state>
+<country>US</country>
+<vpnUrl>https://na10.cloud-vpn.net</vpnUrl>
+<ftpsHost>ftps-na.cloud-vpn.net</ftpsHost>
+<networking type="2" maintenanceStatus="NORMAL">
+<!-- 0-to-many optional property elements -->
+<property name="MAX_NODE_CONNECTION_LIMIT" value="100000"/>
+<property name="MAX_NODE_CONNECTION_RATE_LIMIT" value="4000"/>
+<property name="MAX_VIRTUAL_LISTENER_CONNECTION_LIMIT" value="100000"/>
+<property name="MAX_VIRTUAL_LISTENER_CONNECTION_RATE_LIMIT"
+value="4000"/>
+</networking>
+<hypervisor type="VMWARE" maintenanceStatus="PENDING_MAINTENANCE">
+<diskSpeed available="false" default="false" id="ARCHIVE">
+<displayName>Archive Speed</displayName>
+<abbreviation>ARCH</abbreviation>
+<description>Archive Disk Speed</description>
+<unavailableReason>Replaced with HPF and ECN</unavailableReason>
+</diskSpeed>
+<property name="MIN_DISK_SIZE_GB" value="10"/>
+<property name="MAX_DISK_SIZE_GB" value="1000"/>
+<property name="MAX_TOTAL_ADDITIONAL_STORAGE_GB" value="2500"/>
+<property name="MAX_CPU_COUNT" value="8"/>
+<property name="MIN_MEMORY_MB" value="1024"/>
+<property name="MAX_MEMORY_MB" value="65536"/>
+</hypervisor>
+<!-- Optional: if Cloud Backup is enabled at the Data Center it will be returned -->
+<backup type="COMMVAULT" maintenanceStatus="IN_MAINTENANCE">
+<!-- 0-to-many optional property elements -->
+</backup>
+<consoleAccess maintenanceStatus="IN_MAINTENANCE">
+<!-- 0-to-many optional property elements -->
+</consoleAccess>
+<monitoring maintenanceStatus="IN_MAINTENANCE">
+<!-- 0-to-many optional property elements -->
+</monitoring>
+</datacenter>
+</datacenters>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/libcloud/blob/0ba9ae48/libcloud/test/compute/fixtures/dimensiondata/caas_2_0_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_networkDomain.xml
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/dimensiondata/caas_2_0_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_networkDomain.xml b/libcloud/test/compute/fixtures/dimensiondata/caas_2_0_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_networkDomain.xml
new file mode 100644
index 0000000..22680d1
--- /dev/null
+++ b/libcloud/test/compute/fixtures/dimensiondata/caas_2_0_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_networkDomain.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<networkDomains
+xmlns="urn:didata.com:api:cloud:types" pageNumber="1" pageCount="1"
+totalCount="1" pageSize="250">
+<networkDomain id="484174a2-ae74-4658-9e56-50fc90e086cf" datacenter="NA10">
+<name>Production Network Domain</name>
+<description></description>
+<type>ESSENTIALS</type>
+<snatIpv4Address>165.180.8.8</snatIpv4Address>
+<createTime>2015-02-12T18:18:14.000Z</createTime>
+<state>NORMAL</state>
+</networkDomain>
+</networkDomains>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/libcloud/blob/0ba9ae48/libcloud/test/compute/fixtures/dimensiondata/caas_2_0_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_vlan.xml
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/dimensiondata/caas_2_0_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_vlan.xml b/libcloud/test/compute/fixtures/dimensiondata/caas_2_0_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_vlan.xml
new file mode 100644
index 0000000..b489284
--- /dev/null
+++ b/libcloud/test/compute/fixtures/dimensiondata/caas_2_0_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_vlan.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<vlans
+xmlns="urn:didata.com:api:cloud:types" pageNumber="1" pageCount="1"
+totalCount="1" pageSize="250">
+<vlan id="0e56433f-d808-4669-821d-812769517ff8" location="NA10">
+<networkDomain id="484174a2-ae74-4658-9e56-50fc90e086cf"
+name="Production Network Domain"/>
+<name>Production VLAN</name>
+<description>For hosting our Production Cloud Servers</description>
+<privateIpv4Range address="10.0.3.0" prefixSize="24"/>
+<ipv4GatewayAddress>10.0.3.1</ipv4GatewayAddress>
+<ipv6Range address="2607:f480:1111:1153:0:0:0:0" prefixSize="64"/>
+<ipv6GatewayAddress>2607:f480:1111:1153:0:0:0:1</ipv6GatewayAddress>
+<createTime>2015-02-13T10:56:44.000Z</createTime>
+<state>NORMAL</state>
+</vlan>
+</vlans>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/libcloud/blob/0ba9ae48/libcloud/test/compute/fixtures/dimensiondata/caas_2_0_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_deleteServer.xml
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/dimensiondata/caas_2_0_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_deleteServer.xml b/libcloud/test/compute/fixtures/dimensiondata/caas_2_0_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_deleteServer.xml
new file mode 100644
index 0000000..c8e70da
--- /dev/null
+++ b/libcloud/test/compute/fixtures/dimensiondata/caas_2_0_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_deleteServer.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<response
+xmlns="urn:didata.com:api:cloud:types" requestId="NA9/2015-03-
+08T05:49:07.774-04:00/f0a53414-e991-4c9b-b52f-5770ff5b606b">
+<operation>DELETE_SERVER</operation>
+<responseCode>IN_PROGRESS</responseCode>
+<message>Request to Delete Server (Id:d577a691-e116-4913-a440-
+022d2729fc84) has been accepted and is being processed</message>
+</response>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/libcloud/blob/0ba9ae48/libcloud/test/compute/fixtures/dimensiondata/caas_2_0_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_deleteServer_RESOURCEBUSY.xml
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/dimensiondata/caas_2_0_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_deleteServer_RESOURCEBUSY.xml b/libcloud/test/compute/fixtures/dimensiondata/caas_2_0_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_deleteServer_RESOURCEBUSY.xml
new file mode 100644
index 0000000..2df9e07
--- /dev/null
+++ b/libcloud/test/compute/fixtures/dimensiondata/caas_2_0_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_deleteServer_RESOURCEBUSY.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<response
+xmlns="urn:didata.com:api:cloud:types" requestId="NA9/2015-03-
+08T05:49:07.774-04:00/f0a53414-e991-4c9b-b52f-5770ff5b606b">
+<operation>DELETE_SERVER</operation>
+<responseCode>RESOURCE_BUSY</responseCode>
+<message>Server is already busy</message>
+</response>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/libcloud/blob/0ba9ae48/libcloud/test/compute/fixtures/dimensiondata/caas_2_0_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_powerOffServer.xml
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/dimensiondata/caas_2_0_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_powerOffServer.xml b/libcloud/test/compute/fixtures/dimensiondata/caas_2_0_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_powerOffServer.xml
new file mode 100644
index 0000000..549ea79
--- /dev/null
+++ b/libcloud/test/compute/fixtures/dimensiondata/caas_2_0_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_powerOffServer.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<response xmlns="urn:didata.com:api:cloud:types" requestId="NA9/2015-08-
+12T11:49:17.375-04:00/d5bb0975-1ade-4350-aaec-24807bdf7038">
+<operation>POWER_OFF_SERVER</operation>
+<responseCode>IN_PROGRESS</responseCode>
+<message>Request to power off Server 'Production Server' has been accepted
+and is being processed.</message>
+</response>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/libcloud/blob/0ba9ae48/libcloud/test/compute/fixtures/dimensiondata/caas_2_0_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_powerOffServer_INPROGRESS.xml
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/dimensiondata/caas_2_0_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_powerOffServer_INPROGRESS.xml b/libcloud/test/compute/fixtures/dimensiondata/caas_2_0_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_powerOffServer_INPROGRESS.xml
new file mode 100644
index 0000000..8ddcca9
--- /dev/null
+++ b/libcloud/test/compute/fixtures/dimensiondata/caas_2_0_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_powerOffServer_INPROGRESS.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<response xmlns="urn:didata.com:api:cloud:types" requestId="NA9/2015-08-
+12T11:49:17.375-04:00/d5bb0975-1ade-4350-aaec-24807bdf7038">
+<operation>POWER_OFF_SERVER</operation>
+<responseCode>RESOURCE_BUSY</responseCode>
+<message>Request to power off Server 'Production Server' has been accepted
+and is being processed.</message>
+</response>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/libcloud/blob/0ba9ae48/libcloud/test/compute/fixtures/dimensiondata/caas_2_0_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_rebootServer.xml
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/dimensiondata/caas_2_0_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_rebootServer.xml b/libcloud/test/compute/fixtures/dimensiondata/caas_2_0_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_rebootServer.xml
new file mode 100644
index 0000000..38f098a
--- /dev/null
+++ b/libcloud/test/compute/fixtures/dimensiondata/caas_2_0_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_rebootServer.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<response xmlns="urn:didata.com:api:cloud:types" requestId="NA9/2015-08-
+12T09:52:43.365-04:00/5260a4e5-ea21-49f4-909a-22341d8c39cb">
+<operation>REBOOT_SERVER</operation>
+<responseCode>IN_PROGRESS</responseCode>
+<message>Request to reboot Server 'Production Server' has been accepted
+and is being processed.</message>
+</response>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/libcloud/blob/0ba9ae48/libcloud/test/compute/fixtures/dimensiondata/caas_2_0_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_rebootServer_RESOURCEBUSY.xml
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/dimensiondata/caas_2_0_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_rebootServer_RESOURCEBUSY.xml b/libcloud/test/compute/fixtures/dimensiondata/caas_2_0_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_rebootServer_RESOURCEBUSY.xml
new file mode 100644
index 0000000..3defba4
--- /dev/null
+++ b/libcloud/test/compute/fixtures/dimensiondata/caas_2_0_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_rebootServer_RESOURCEBUSY.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<response xmlns="urn:didata.com:api:cloud:types" requestId="NA9/2015-08-
+12T09:52:43.365-04:00/5260a4e5-ea21-49f4-909a-22341d8c39cb">
+<operation>REBOOT_SERVER</operation>
+<responseCode>RESOURCE_BUSY</responseCode>
+<message>Request to reboot Server 'Production Server' did not work, server is busy.</message>
+</response>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/libcloud/blob/0ba9ae48/libcloud/test/compute/fixtures/dimensiondata/caas_2_0_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_resetServer.xml
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/dimensiondata/caas_2_0_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_resetServer.xml b/libcloud/test/compute/fixtures/dimensiondata/caas_2_0_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_resetServer.xml
new file mode 100644
index 0000000..ece1a8b
--- /dev/null
+++ b/libcloud/test/compute/fixtures/dimensiondata/caas_2_0_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_resetServer.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<response xmlns="urn:didata.com:api:cloud:types" requestId="NA9/2015-08-
+12T11:37:13.823-04:00/7b264a73-d73b-424c-bec8-5debba8b4626">
+<operation>RESET_SERVER</operation>
+<responseCode>IN_PROGRESS</responseCode>
+<message>Request to reset Server 'Production Server' has been accepted and
+is being processed.</message>
+</response>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/libcloud/blob/0ba9ae48/libcloud/test/compute/fixtures/dimensiondata/caas_2_0_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_server.xml
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/dimensiondata/caas_2_0_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_server.xml b/libcloud/test/compute/fixtures/dimensiondata/caas_2_0_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_server.xml
new file mode 100644
index 0000000..bc98272
--- /dev/null
+++ b/libcloud/test/compute/fixtures/dimensiondata/caas_2_0_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_server.xml
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<servers
+xmlns="urn:didata.com:api:cloud:types" pageNumber="1" pageCount="1"
+totalCount="2" pageSize="250">
+<Server id="d577a691-e116-4913-a440-022d2729fc84" datacenterId="NA9">
+<name>Test Server</name>
+<description>Test Description</description>
+<operatingSystem id="REDHAT664" displayName="REDHAT6/64"
+family="UNIX"/>
+<cpuCount>1</cpuCount>
+<memoryGb>2</memoryGb>
+<disk id="338c1163-5348-4572-962d-185c97bd0d65" scsiId="0" sizeGb="10"
+speed="STANDARD" state="NORMAL"/>
+<networkInfo networkDomainId="484174a2-ae74-4658-9e56-50fc90e086cf">
+<primaryNic id="4c8d5f67-c6df-421d-b8ac-45dd1b141334"
+privateIpv4="10.0.3.11" ipv6="2607:f480:1111:1153:dee:4666:1130:7484"
+vlanId="0e56433f-d808-4669-821d-812769517ff8" vlanName="Production VLAN"
+state="NORMAL"/>
+</networkInfo>
+<sourceImageId>02250336-de2b-4e99-ab96-78511b7f8f4b</sourceImageId>
+<createTime>2015-02-17T10:59:18.000Z</createTime>
+<deployed>true</deployed>
+<started>true</started>
+<state>NORMAL</state>
+<machineStatus name="vmwareToolsVersionStatus" value="CURRENT"/>
+<machineStatus name="vmwareToolsRunningStatus" value="RUNNING"/>
+<machineStatus name="vmwareToolsApiVersion" value="9354"/>
+</Server>
+<Server id="abadbc7e-9e10-46ca-9d4a-194bcc6b6c16" datacenterId="NA9">
+<name>Production Web Server 2</name>
+<description>This server hosts our production web
+applications.</description>
+<operatingSystem id="REDHAT664" displayName="REDHAT6/64"
+family="UNIX"/>
+<cpuCount>1</cpuCount>
+<memoryGb>2</memoryGb>
+<disk id="338c1163-5348-4572-962d-185c97bd0d65" scsiId="0" sizeGb="10"
+speed="STANDARD" state="NORMAL"/>
+<networkInfo networkDomainId="484174a2-ae74-4658-9e56-50fc90e086cf">
+<primaryNic id="4c8d5f67-c6df-421d-b8ac-45dd1b141334"
+privateIpv4="10.0.3.11" ipv6="2607:f480:1111:1153:dee:4666:1130:7484"
+vlanId="0e56433f-d808-4669-821d-812769517ff8" vlanName="Production VLAN"
+state="NORMAL"/>
+</networkInfo>
+<sourceImageId>02250336-de2b-4e99-ab96-78511b7f8f4b</sourceImageId>
+<createTime>2015-02-17T10:59:18.000Z</createTime>
+<deployed>true</deployed>
+<started>true</started>
+<state>PENDING_CHANGE</state>
+<progress>
+<action>SHUTDOWN_SERVER</action>
+<requestTime>2015-03-06T18:05:33.000Z</requestTime>
+<userName>myuser</userName>
+</progress>
+<machineStatus name="vmwareToolsVersionStatus" value="CURRENT"/>
+<machineStatus name="vmwareToolsRunningStatus" value="RUNNING"/>
+<machineStatus name="vmwareToolsApiVersion" value="9354"/>
+</Server>
+</servers>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/libcloud/blob/0ba9ae48/libcloud/test/compute/fixtures/dimensiondata/caas_2_0_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_shutdownServer.xml
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/dimensiondata/caas_2_0_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_shutdownServer.xml b/libcloud/test/compute/fixtures/dimensiondata/caas_2_0_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_shutdownServer.xml
new file mode 100644
index 0000000..937cb0d
--- /dev/null
+++ b/libcloud/test/compute/fixtures/dimensiondata/caas_2_0_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_shutdownServer.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<response xmlns="urn:didata.com:api:cloud:types" requestId="NA9/2015-08-
+12T09:06:01.949-04:00/fd2650a9-3473-41eb-9c6e-1eef29c0bb27">
+<operation>SHUTDOWN_SERVER</operation>
+<responseCode>IN_PROGRESS</responseCode>
+<message>Request to shutdown Server 'Production Server' has been accepted
+and is being processed.</message>
+</response>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/libcloud/blob/0ba9ae48/libcloud/test/compute/fixtures/dimensiondata/caas_2_0_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_shutdownServer_INPROGRESS.xml
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/dimensiondata/caas_2_0_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_shutdownServer_INPROGRESS.xml b/libcloud/test/compute/fixtures/dimensiondata/caas_2_0_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_shutdownServer_INPROGRESS.xml
new file mode 100644
index 0000000..386489c
--- /dev/null
+++ b/libcloud/test/compute/fixtures/dimensiondata/caas_2_0_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_shutdownServer_INPROGRESS.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<response xmlns="urn:didata.com:api:cloud:types" requestId="NA9/2015-08-
+12T09:06:01.949-04:00/fd2650a9-3473-41eb-9c6e-1eef29c0bb27">
+<operation>SHUTDOWN_SERVER</operation>
+<responseCode>RESOURCE_BUSY</responseCode>
+<message>Request to shutdown Server 'Production Server' has been accepted
+and is being processed.</message>
+</response>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/libcloud/blob/0ba9ae48/libcloud/test/compute/fixtures/dimensiondata/caas_2_0_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_startServer.xml
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/dimensiondata/caas_2_0_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_startServer.xml b/libcloud/test/compute/fixtures/dimensiondata/caas_2_0_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_startServer.xml
new file mode 100644
index 0000000..4fb4589
--- /dev/null
+++ b/libcloud/test/compute/fixtures/dimensiondata/caas_2_0_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_startServer.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<response xmlns="urn:didata.com:api:cloud:types" requestId="NA9/2015-08-
+12T08:27:00.176-04:00/14b0a61f-7e85-49c9-8e7e-146fa3e562b7">
+<operation>START_SERVER</operation>
+<responseCode>IN_PROGRESS</responseCode>
+<message>Request to start Server 'Production Server' has been accepted and
+is being processed.</message>
+</response>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/libcloud/blob/0ba9ae48/libcloud/test/compute/fixtures/dimensiondata/caas_2_0_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_startServer_INPROGRESS.xml
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/dimensiondata/caas_2_0_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_startServer_INPROGRESS.xml b/libcloud/test/compute/fixtures/dimensiondata/caas_2_0_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_startServer_INPROGRESS.xml
new file mode 100644
index 0000000..f5c3070
--- /dev/null
+++ b/libcloud/test/compute/fixtures/dimensiondata/caas_2_0_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_startServer_INPROGRESS.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<response xmlns="urn:didata.com:api:cloud:types" requestId="NA9/2015-08-
+12T08:27:00.176-04:00/14b0a61f-7e85-49c9-8e7e-146fa3e562b7">
+<operation>START_SERVER</operation>
+<responseCode>RESOURCE_BUSY</responseCode>
+<message>Request to start Server 'Production Server' has been accepted and
+is being processed.</message>
+</response>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/libcloud/blob/0ba9ae48/libcloud/test/compute/fixtures/dimensiondata/oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkWithLocation.xml
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/dimensiondata/oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkWithLocation.xml b/libcloud/test/compute/fixtures/dimensiondata/oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkWithLocation.xml
index ca27554..88364b6 100644
--- a/libcloud/test/compute/fixtures/dimensiondata/oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkWithLocation.xml
+++ b/libcloud/test/compute/fixtures/dimensiondata/oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkWithLocation.xml
@@ -4,7 +4,7 @@
         <ns4:id>53b4c05b-341e-4ac3-b688-bdd74e53ca9b</ns4:id>
         <ns4:name>test-net1</ns4:name>
         <ns4:description>test-net1 description</ns4:description>
-        <ns4:location>NA1</ns4:location>
+        <ns4:location>NA10</ns4:location>
         <ns4:privateNet>10.162.1.0</ns4:privateNet>
         <ns4:multicast>false</ns4:multicast>
     </ns4:network>

http://git-wip-us.apache.org/repos/asf/libcloud/blob/0ba9ae48/libcloud/test/compute/fixtures/dimensiondata/oec_0_9_base_image.xml
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/dimensiondata/oec_0_9_base_image.xml b/libcloud/test/compute/fixtures/dimensiondata/oec_0_9_base_image.xml
index 3be14f0..d758343 100644
--- a/libcloud/test/compute/fixtures/dimensiondata/oec_0_9_base_image.xml
+++ b/libcloud/test/compute/fixtures/dimensiondata/oec_0_9_base_image.xml
@@ -9,7 +9,7 @@
             <type>UNIX</type>
             <displayName>REDHAT5/64</displayName>
         </operatingSystem>
-        <location>NA1</location>
+        <location>NA10</location>
         <cpuCount>1</cpuCount>
         <memory>2048</memory>
         <osStorage>10</osStorage>
@@ -25,7 +25,7 @@
             <type>UNIX</type>
             <displayName>REDHAT5/64</displayName>
         </operatingSystem>
-        <location>NA1</location>
+        <location>NA10</location>
         <cpuCount>2</cpuCount>
         <memory>4096</memory>
         <osStorage>10</osStorage>
@@ -41,7 +41,7 @@
             <type>UNIX</type>
             <displayName>REDHAT5/64</displayName>
         </operatingSystem>
-        <location>NA1</location>
+        <location>NA10</location>
         <cpuCount>4</cpuCount>
         <memory>6144</memory>
         <osStorage>10</osStorage>
@@ -57,7 +57,7 @@
             <type>UNIX</type>
             <displayName>REDHAT5/32</displayName>
         </operatingSystem>
-        <location>NA1</location>
+        <location>NA10</location>
         <cpuCount>1</cpuCount>
         <memory>2048</memory>
         <osStorage>10</osStorage>
@@ -73,7 +73,7 @@
             <type>UNIX</type>
             <displayName>UBUNTU8/64</displayName>
         </operatingSystem>
-        <location>NA1</location>
+        <location>NA10</location>
         <cpuCount>2</cpuCount>
         <memory>4096</memory>
         <osStorage>10</osStorage>
@@ -89,7 +89,7 @@
             <type>WINDOWS</type>
             <displayName>WIN2008R2E/64</displayName>
         </operatingSystem>
-        <location>NA1</location>
+        <location>NA10</location>
         <cpuCount>2</cpuCount>
         <memory>4096</memory>
         <osStorage>50</osStorage>
@@ -105,7 +105,7 @@
             <type>WINDOWS</type>
             <displayName>WIN2008R2E/64</displayName>
         </operatingSystem>
-        <location>NA1</location>
+        <location>NA10</location>
         <cpuCount>4</cpuCount>
         <memory>8192</memory>
         <osStorage>50</osStorage>
@@ -121,7 +121,7 @@
             <type>WINDOWS</type>
             <displayName>WIN2008R2S/64</displayName>
         </operatingSystem>
-        <location>NA1</location>
+        <location>NA10</location>
         <cpuCount>2</cpuCount>
         <memory>4096</memory>
         <osStorage>50</osStorage>
@@ -137,7 +137,7 @@
             <type>WINDOWS</type>
             <displayName>WIN2008S/32</displayName>
         </operatingSystem>
-        <location>NA1</location>
+        <location>NA10</location>
         <cpuCount>1</cpuCount>
         <memory>2048</memory>
         <osStorage>50</osStorage>
@@ -153,7 +153,7 @@
             <type>WINDOWS</type>
             <displayName>WIN2008S/32</displayName>
         </operatingSystem>
-        <location>NA1</location>
+        <location>NA10</location>
         <cpuCount>2</cpuCount>
         <memory>4096</memory>
         <osStorage>50</osStorage>
@@ -169,7 +169,7 @@
             <type>WINDOWS</type>
             <displayName>WIN2008S/32</displayName>
         </operatingSystem>
-        <location>NA1</location>
+        <location>NA10</location>
         <cpuCount>4</cpuCount>
         <memory>4096</memory>
         <osStorage>50</osStorage>
@@ -185,7 +185,7 @@
             <type>WINDOWS</type>
             <displayName>WIN2008E/32</displayName>
         </operatingSystem>
-        <location>NA1</location>
+        <location>NA10</location>
         <cpuCount>2</cpuCount>
         <memory>4096</memory>
         <osStorage>50</osStorage>
@@ -201,7 +201,7 @@
             <type>UNIX</type>
             <displayName>REDHAT4/32</displayName>
         </operatingSystem>
-        <location>NA1</location>
+        <location>NA10</location>
         <cpuCount>1</cpuCount>
         <memory>2048</memory>
         <osStorage>10</osStorage>
@@ -217,123 +217,11 @@
             <type>UNIX</type>
             <displayName>CENTOS5/32</displayName>
         </operatingSystem>
-        <location>NA1</location>
+        <location>NA10</location>
         <cpuCount>1</cpuCount>
         <memory>2048</memory>
         <osStorage>10</osStorage>
         <additionalLocalStorage>0</additionalLocalStorage>
         <created>1970-01-01T00:00:02.010Z</created>
     </ServerImage>
-    <ServerImage>
-        <id>52ed91da-ebea-11df-bdc1-001517c46384</id>
-        <resourcePath>/oec/base/image/52ed91da-ebea-11df-bdc1-001517c46384</resourcePath>
-        <name>CentOS 5.5 64-bit 1 CPU</name>
-        <description>CentOS release 5.5, 64-bit</description>
-        <operatingSystem>
-            <type>UNIX</type>
-            <displayName>CENTOS5/64</displayName>
-        </operatingSystem>
-        <location>NA1</location>
-        <cpuCount>1</cpuCount>
-        <memory>2048</memory>
-        <osStorage>10</osStorage>
-        <additionalLocalStorage>0</additionalLocalStorage>
-        <created>1970-01-01T00:00:02.010Z</created>
-    </ServerImage>
-    <ServerImage>
-        <id>52ed766e-ebea-11df-bdc1-001517c46384</id>
-        <resourcePath>/oec/base/image/52ed766e-ebea-11df-bdc1-001517c46384</resourcePath>
-        <name>Win2003 Ent 32-bit 1 CPU</name>
-        <description>Windows 2003 Enterprise SP2 32-bit</description>
-        <operatingSystem>
-            <type>WINDOWS</type>
-            <displayName>WIN2003E/32</displayName>
-        </operatingSystem>
-        <location>NA1</location>
-        <cpuCount>1</cpuCount>
-        <memory>2048</memory>
-        <osStorage>16</osStorage>
-        <additionalLocalStorage>0</additionalLocalStorage>
-        <created>1970-01-01T00:00:02.010Z</created>
-    </ServerImage>
-    <ServerImage>
-        <id>52ed7876-ebea-11df-bdc1-001517c46384</id>
-        <resourcePath>/oec/base/image/52ed7876-ebea-11df-bdc1-001517c46384</resourcePath>
-        <name>Win2003 Ent 32-bit 2 CPU</name>
-        <description>Windows 2003 Enterprise SP2 32-bit</description>
-        <operatingSystem>
-            <type>WINDOWS</type>
-            <displayName>WIN2003E/32</displayName>
-        </operatingSystem>
-        <location>NA1</location>
-        <cpuCount>2</cpuCount>
-        <memory>4096</memory>
-        <osStorage>16</osStorage>
-        <additionalLocalStorage>0</additionalLocalStorage>
-        <created>1970-01-01T00:00:02.010Z</created>
-    </ServerImage>
-    <ServerImage>
-        <id>52ed7984-ebea-11df-bdc1-001517c46384</id>
-        <resourcePath>/oec/base/image/52ed7984-ebea-11df-bdc1-001517c46384</resourcePath>
-        <name>Win2003 Ent 32-bit 4 CPU</name>
-        <description>Windows 2003 Enterprise SP2 32-bit</description>
-        <operatingSystem>
-            <type>WINDOWS</type>
-            <displayName>WIN2003E/32</displayName>
-        </operatingSystem>
-        <location>NA1</location>
-        <cpuCount>4</cpuCount>
-        <memory>4096</memory>
-        <osStorage>16</osStorage>
-        <additionalLocalStorage>0</additionalLocalStorage>
-        <created>1970-01-01T00:00:02.010Z</created>
-    </ServerImage>
-    <ServerImage>
-        <id>52ed7a88-ebea-11df-bdc1-001517c46384</id>
-        <resourcePath>/oec/base/image/52ed7a88-ebea-11df-bdc1-001517c46384</resourcePath>
-        <name>Win2003 Std 64-bit 2 CPU</name>
-        <description>Windows 2003 Standard x64 SP2, 64-bit</description>
-        <operatingSystem>
-            <type>WINDOWS</type>
-            <displayName>WIN2003S/64</displayName>
-        </operatingSystem>
-        <location>NA1</location>
-        <cpuCount>2</cpuCount>
-        <memory>4096</memory>
-        <osStorage>16</osStorage>
-        <additionalLocalStorage>0</additionalLocalStorage>
-        <created>1970-01-01T00:00:02.010Z</created>
-    </ServerImage>
-    <ServerImage>
-        <id>0c231ef0-2a42-11e0-bfb5-001517c46384</id>
-        <resourcePath>/oec/base/image/0c231ef0-2a42-11e0-bfb5-001517c46384</resourcePath>
-        <name>RedHat 64-bit 2 CPU with MySQL</name>
-        <description>RedHat 5.5 Enterprise with MySQL 5.5 installed</description>
-        <operatingSystem>
-            <type>UNIX</type>
-            <displayName>REDHAT5/64</displayName>
-        </operatingSystem>
-        <location>NA1</location>
-        <cpuCount>2</cpuCount>
-        <memory>8192</memory>
-        <osStorage>10</osStorage>
-        <additionalLocalStorage>0</additionalLocalStorage>
-        <created>2011-01-27T18:19:58.000Z</created>
-    </ServerImage>
-    <ServerImage>
-        <id>2fb5261a-2a42-11e0-bfb5-001517c46384</id>
-        <resourcePath>/oec/base/image/2fb5261a-2a42-11e0-bfb5-001517c46384</resourcePath>
-        <name>RedHat 64-bit 2 CPU with PostgreSQL</name>
-        <description>RedHat 5.5 Enterprise with PostgreSQL 9.0 installed</description>
-        <operatingSystem>
-            <type>UNIX</type>
-            <displayName>REDHAT5/64</displayName>
-        </operatingSystem>
-        <location>NA1</location>
-        <cpuCount>2</cpuCount>
-        <memory>8192</memory>
-        <osStorage>10</osStorage>
-        <additionalLocalStorage>0</additionalLocalStorage>
-        <created>2011-01-27T18:20:57.000Z</created>
-    </ServerImage>
 </ServerImages>

http://git-wip-us.apache.org/repos/asf/libcloud/blob/0ba9ae48/libcloud/test/compute/test_dimensiondata.py
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/test_dimensiondata.py b/libcloud/test/compute/test_dimensiondata.py
index 47a8e16..d6c4dba 100644
--- a/libcloud/test/compute/test_dimensiondata.py
+++ b/libcloud/test/compute/test_dimensiondata.py
@@ -20,6 +20,7 @@ from libcloud.common.types import InvalidCredsError
 from libcloud.compute.drivers.dimensiondata import DimensionDataNodeDriver as DimensionData
 from libcloud.compute.drivers.dimensiondata import DimensionDataAPIException
 from libcloud.compute.base import Node, NodeAuthPassword, NodeLocation
+from libcloud.compute.types import NodeState
 
 from libcloud.test import MockHttp
 from libcloud.test.compute import TestCaseMixin
@@ -44,6 +45,21 @@ class DimensionDataTests(unittest.TestCase, TestCaseMixin):
         except InvalidCredsError:
             pass
 
+    def test_list_locations_response(self):
+        DimensionDataMockHttp.type = None
+        ret = self.driver.list_locations()
+        self.assertEqual(len(ret), 1)
+        first_node = ret[0]
+        self.assertEqual(first_node.id, 'NA10')
+        self.assertEqual(first_node.name, 'US - West')
+        self.assertEqual(first_node.country, 'US')
+        
+    def test_list_nodes_response(self):
+        DimensionDataMockHttp.type = None
+        ret = self.driver.list_nodes()
+        self.assertEqual(len(ret), 2)
+        first_node = ret[0]
+        
     def test_list_sizes_response(self):
         DimensionDataMockHttp.type = None
         ret = self.driver.list_sizes()
@@ -74,7 +90,7 @@ class DimensionDataTests(unittest.TestCase, TestCaseMixin):
         ret = node.destroy()
         self.assertTrue(ret is True)
 
-    def test_destroy_node_response_INPROGRESS(self):
+    def test_destroy_node_response_RESOURCE_BUSY(self):
         DimensionDataMockHttp.type = 'INPROGRESS'
         node = Node(id='11', name=None, state=None,
                     public_ips=None, private_ips=None, driver=self.driver)
@@ -146,17 +162,26 @@ class DimensionDataTests(unittest.TestCase, TestCaseMixin):
         except DimensionDataAPIException:
             pass
 
+    def test_ex_reset(self):
+        node = Node(id='11', name=None, state=None,
+                    public_ips=None, private_ips=None, driver=self.driver)
+        ret = self.driver.ex_reset(node)
+        self.assertTrue(ret is True)
+
     def test_ex_list_networks(self):
         nets = self.driver.ex_list_networks()
         self.assertEqual(nets[0].name, 'test-net1')
         self.assertTrue(isinstance(nets[0].location, NodeLocation))
+        
+    def test_ex_list_network_domains(self):
+        nets = self.driver.ex_list_network_domains()
+        self.assertEqual(nets[0].name, 'Production Network Domain')
+        self.assertTrue(isinstance(nets[0].location, NodeLocation))
 
-    def test_node_public_ip(self):
-        nodes = self.driver.list_nodes()
-        node = [n for n in nodes if n.id ==
-                'abadbc7e-9e10-46ca-9d4a-194bcc6b6c16'][0]
-        self.assertEqual(node.public_ips[0], '200.16.132.7')
-
+    def test_ex_list_vlans(self):
+        vlans = self.driver.ex_list_vlans()
+        self.assertEqual(vlans[0].name, "Production VLAN")
+            
 
 class DimensionDataMockHttp(MockHttp):
 
@@ -245,7 +270,86 @@ class DimensionDataMockHttp(MockHttp):
         body = self.fixtures.load(
             'oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkWithLocation.xml')
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+    
+    def _caas_2_0_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server(self, method, url, body, headers):
+        body = self.fixtures.load(
+            'caas_2_0_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server.xml')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
-
+    def _caas_2_0_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_deleteServer(self, method, url, body, headers):
+        body = self.fixtures.load(
+            'caas_2_0_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_deleteServer.xml')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+    
+    def _caas_2_0_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_deleteServer_INPROGRESS(self, method, url, body, headers):
+        body = self.fixtures.load(
+            'caas_2_0_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_deleteServer_RESOURCEBUSY.xml')
+        return (httplib.BAD_REQUEST, body, {}, httplib.responses[httplib.OK])
+    
+    def _caas_2_0_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_rebootServer(self, method, url, body, headers):
+        body = self.fixtures.load(
+            'caas_2_0_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_rebootServer.xml')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+    
+    def _caas_2_0_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_rebootServer_INPROGRESS(self, method, url, body, headers):
+        body = self.fixtures.load(
+            'caas_2_0_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_rebootServer_RESOURCEBUSY.xml')
+        return (httplib.BAD_REQUEST, body, {}, httplib.responses[httplib.OK])
+    
+    def _caas_2_0_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_server(self, method, url, body, headers):
+        body = self.fixtures.load(
+            'caas_2_0_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_server.xml')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+    
+    def _caas_2_0_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_infrastructure_datacenter(self, method, url, body, headers):
+        body = self.fixtures.load(
+            'caas_2_0_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_infrastructure_datacenter.xml')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+    
+    def _caas_2_0_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_startServer(self, method, url, body, headers):
+        body = self.fixtures.load(
+            'caas_2_0_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_startServer.xml')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+    
+    def _caas_2_0_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_startServer_INPROGRESS(self, method, url, body, headers):
+        body = self.fixtures.load(
+            'caas_2_0_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_startServer_INPROGRESS.xml')
+        return (httplib.BAD_REQUEST, body, {}, httplib.responses[httplib.OK])
+    
+    def _caas_2_0_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_shutdownServer(self, method, url, body, headers):
+        body = self.fixtures.load(
+            'caas_2_0_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_shutdownServer.xml')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+    
+    def _caas_2_0_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_shutdownServer_INPROGRESS(self, method, url, body, headers):
+        body = self.fixtures.load(
+            'caas_2_0_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_shutdownServer_INPROGRESS.xml')
+        return (httplib.BAD_REQUEST, body, {}, httplib.responses[httplib.OK])
+    
+    def _caas_2_0_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_resetServer(self, method, url, body, headers):
+        body = self.fixtures.load(
+            'caas_2_0_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_resetServer.xml')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+    
+    def _caas_2_0_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_powerOffServer(self, method, url, body, headers):
+        body = self.fixtures.load(
+            'caas_2_0_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_powerOffServer.xml')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+    
+    def _caas_2_0_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_powerOffServer_INPROGRESS(self, method, url, body, headers):
+        body = self.fixtures.load(
+            'caas_2_0_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_powerOffServer_INPROGRESS.xml')
+        return (httplib.BAD_REQUEST, body, {}, httplib.responses[httplib.OK])
+    
+    def _caas_2_0_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_networkDomain(self, method, url, body, headers):
+        body = self.fixtures.load(
+            'caas_2_0_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_networkDomain.xml')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+    
+    def _caas_2_0_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_vlan(self, method, url, body, headers):
+        body = self.fixtures.load(
+            'caas_2_0_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_vlan.xml')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+    
 if __name__ == '__main__':
     sys.exit(unittest.main())