You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@libcloud.apache.org by an...@apache.org on 2016/12/02 04:33:03 UTC

[01/40] libcloud git commit: Enable specifying api version

Repository: libcloud
Updated Branches:
  refs/heads/trunk 216a24fbe -> 75b129e8b


Enable specifying api version


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

Branch: refs/heads/trunk
Commit: f4caab373b18e3c02cdfe3e4580cb03efb7a9199
Parents: 9e5976c
Author: Samuel Chong <sa...@gmail.com>
Authored: Thu Nov 3 11:10:07 2016 +1100
Committer: Samuel Chong <sa...@gmail.com>
Committed: Thu Nov 3 11:10:07 2016 +1100

----------------------------------------------------------------------
 libcloud/common/dimensiondata.py          | 7 ++++++-
 libcloud/compute/drivers/dimensiondata.py | 4 ++++
 2 files changed, 10 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/libcloud/blob/f4caab37/libcloud/common/dimensiondata.py
----------------------------------------------------------------------
diff --git a/libcloud/common/dimensiondata.py b/libcloud/common/dimensiondata.py
index bdcde5a..0a868b8 100644
--- a/libcloud/common/dimensiondata.py
+++ b/libcloud/common/dimensiondata.py
@@ -382,7 +382,8 @@ class DimensionDataConnection(ConnectionUserAndKey):
     allow_insecure = False
 
     def __init__(self, user_id, key, secure=True, host=None, port=None,
-                 url=None, timeout=None, proxy_url=None, **conn_kwargs):
+                 url=None, timeout=None, proxy_url=None,
+                 api_version=None, **conn_kwargs):
         super(DimensionDataConnection, self).__init__(
             user_id=user_id,
             key=key,
@@ -394,6 +395,10 @@ class DimensionDataConnection(ConnectionUserAndKey):
         if conn_kwargs['region']:
             self.host = conn_kwargs['region']['host']
 
+        if api_version:
+            if api_version.startswith('2'):
+                self.api_version_2 = api_version
+
     def add_default_headers(self, headers):
         headers['Authorization'] = \
             ('Basic %s' % b64encode(b('%s:%s' % (self.user_id,

http://git-wip-us.apache.org/repos/asf/libcloud/blob/f4caab37/libcloud/compute/drivers/dimensiondata.py
----------------------------------------------------------------------
diff --git a/libcloud/compute/drivers/dimensiondata.py b/libcloud/compute/drivers/dimensiondata.py
index 76dfb55..9e477b6 100644
--- a/libcloud/compute/drivers/dimensiondata.py
+++ b/libcloud/compute/drivers/dimensiondata.py
@@ -114,6 +114,9 @@ class DimensionDataNodeDriver(NodeDriver):
         if region is not None:
             self.selected_region = API_ENDPOINTS[region]
 
+        if api_version is not None:
+            self.api_version = api_version
+
         super(DimensionDataNodeDriver, self).__init__(key=key, secret=secret,
                                                       secure=secure, host=host,
                                                       port=port,
@@ -129,6 +132,7 @@ class DimensionDataNodeDriver(NodeDriver):
         kwargs = super(DimensionDataNodeDriver,
                        self)._ex_connection_class_kwargs()
         kwargs['region'] = self.selected_region
+        kwargs['api_version'] = self.api_version
         return kwargs
 
     def _create_node_mcp1(self, name, image, auth, ex_description,


[25/40] libcloud git commit: Merge remote-tracking branch 'apache/trunk' into enable_api_version

Posted by an...@apache.org.
Merge remote-tracking branch 'apache/trunk' into enable_api_version


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

Branch: refs/heads/trunk
Commit: aeb03d80c7459b7a27e5bdde281f0a94c4b41066
Parents: cd7fe0e fe34a54
Author: Samuel Chong <sa...@gmail.com>
Authored: Fri Nov 18 11:33:10 2016 +1100
Committer: Samuel Chong <sa...@gmail.com>
Committed: Fri Nov 18 11:33:10 2016 +1100

----------------------------------------------------------------------
 CHANGES.rst                                     |   46 +
 .../_supported_methods_block_storage.rst        |    6 +-
 .../_supported_methods_key_pair_management.rst  |    2 +-
 docs/compute/_supported_providers.rst           |    2 +-
 docs/compute/drivers/azure.rst                  |   14 +-
 docs/compute/drivers/azure_arm.rst              |   54 +
 docs/compute/drivers/ec2.rst                    |    1 +
 docs/container/_supported_methods.rst           |    2 +-
 docs/examples/compute/azure_arm/instantiate.py  |    7 +
 docs/loadbalancer/_supported_methods.rst        |    2 +
 docs/loadbalancer/_supported_providers.rst      |    2 +
 docs/other/hacktoberfest.txt                    |    9 +-
 docs/storage/_supported_methods_cdn.rst         |    2 +
 docs/storage/_supported_methods_main.rst        |    2 +
 docs/storage/_supported_providers.rst           |    2 +
 libcloud/__init__.py                            |    2 +-
 libcloud/common/azure.py                        |    2 +
 libcloud/common/azure_arm.py                    |  124 +
 libcloud/common/base.py                         |   19 +-
 libcloud/common/cloudsigma.py                   |    5 +
 libcloud/common/google.py                       |    4 +-
 libcloud/compute/drivers/azure_arm.py           | 1281 +++++
 libcloud/compute/drivers/ec2.py                 |   65 +-
 libcloud/compute/drivers/ecs.py                 |   27 +-
 libcloud/compute/drivers/gce.py                 |   20 +-
 libcloud/compute/drivers/profitbricks.py        | 4101 ++++++++++---
 libcloud/compute/providers.py                   |    2 +
 libcloud/compute/types.py                       |    7 +-
 libcloud/loadbalancer/drivers/alb.py            |  321 ++
 libcloud/loadbalancer/providers.py              |    2 +
 libcloud/loadbalancer/types.py                  |    1 +
 libcloud/storage/drivers/s3.py                  |   12 +
 libcloud/storage/providers.py                   |    2 +
 libcloud/storage/types.py                       |    2 +
 libcloud/test/common/test_google.py             |   13 +-
 ...777_7777_7777_777777777777_oauth2_token.json |    1 +
 ...99999999999_providers_Microsoft_Compute.json |  200 +
 ...rosoft_Compute_locations_eastus_vmSizes.json |   28 +
 .../compute/fixtures/ecs/create_public_ip.xml   |    6 +
 .../fixtures/profitbricks/attach_volume.json    |   34 +
 .../fixtures/profitbricks/attach_volume.xml     |   12 -
 .../fixtures/profitbricks/create_node.json      |   37 +
 .../fixtures/profitbricks/create_node.xml       |   13 -
 .../fixtures/profitbricks/create_volume.json    |   35 +
 .../fixtures/profitbricks/create_volume.xml     |   13 -
 .../profitbricks/create_volume_snapshot.json    |   30 +
 .../fixtures/profitbricks/destroy_node.xml      |   12 -
 .../fixtures/profitbricks/destroy_volume.xml    |   12 -
 .../fixtures/profitbricks/detach_volume.xml     |   12 -
 .../profitbricks/ex_clear_datacenter.xml        |   12 -
 .../profitbricks/ex_create_datacenter.json      |   20 +
 .../profitbricks/ex_create_datacenter.xml       |   13 -
 .../profitbricks/ex_create_firewall_rule.json   |   24 +
 .../profitbricks/ex_create_ip_block.json        |   22 +
 .../fixtures/profitbricks/ex_create_lan.json    |   17 +
 .../profitbricks/ex_create_load_balancer.json   |   18 +
 .../ex_create_network_interface.json            |   22 +
 .../ex_create_network_interface.xml             |   13 -
 .../profitbricks/ex_describe_datacenter.json    |  401 ++
 .../profitbricks/ex_describe_datacenter.xml     |   15 -
 .../profitbricks/ex_describe_firewall_rule.json |   24 +
 .../profitbricks/ex_describe_image.json         |   32 +
 .../profitbricks/ex_describe_ip_block.json      |   21 +
 .../fixtures/profitbricks/ex_describe_lan.json  |   24 +
 .../profitbricks/ex_describe_load_balancer.json |   25 +
 .../profitbricks/ex_describe_location.json      |   12 +
 .../ex_describe_network_interface.json          |   31 +
 .../ex_describe_network_interface.xml           |   26 -
 .../fixtures/profitbricks/ex_describe_node.json |  111 +
 .../fixtures/profitbricks/ex_describe_node.xml  |   77 -
 .../profitbricks/ex_describe_snapshot.json      |   30 +
 .../profitbricks/ex_describe_volume.json        |   35 +
 .../profitbricks/ex_describe_volume.xml         |   22 -
 .../profitbricks/ex_destroy_datacenter.xml      |   10 -
 .../ex_destroy_network_interface.xml            |   12 -
 .../profitbricks/ex_list_attached_volumes.json  |  112 +
 .../profitbricks/ex_list_datacenters.json       |   52 +
 .../profitbricks/ex_list_datacenters.xml        |   19 -
 .../profitbricks/ex_list_firewall_rules.json    |   79 +
 .../profitbricks/ex_list_ip_blocks.json         |   50 +
 .../fixtures/profitbricks/ex_list_lans.json     |  157 +
 .../ex_list_load_balanced_nics.json             |   69 +
 .../profitbricks/ex_list_load_balancers.json    |  216 +
 .../ex_list_network_interfaces.json             |   69 +
 .../profitbricks/ex_list_network_interfaces.xml |   75 -
 .../profitbricks/ex_rename_datacenter.json      |   46 +
 .../profitbricks/ex_set_inet_access.json        |   31 +
 .../fixtures/profitbricks/ex_start_node.xml     |   10 -
 .../fixtures/profitbricks/ex_stop_node.xml      |   10 -
 .../profitbricks/ex_update_datacenter.xml       |   12 -
 .../profitbricks/ex_update_firewall_rule.json   |   25 +
 .../fixtures/profitbricks/ex_update_image.json  |   32 +
 .../fixtures/profitbricks/ex_update_lan.json    |   24 +
 .../profitbricks/ex_update_load_balancer.json   |   18 +
 .../ex_update_network_interface.json            |   31 +
 .../ex_update_network_interface.xml             |   12 -
 .../fixtures/profitbricks/ex_update_node.json   |   45 +
 .../fixtures/profitbricks/ex_update_node.xml    |   12 -
 .../profitbricks/ex_update_snapshot.json        |   30 +
 .../fixtures/profitbricks/ex_update_volume.json |   35 +
 .../fixtures/profitbricks/ex_update_volume.xml  |   12 -
 .../fixtures/profitbricks/list_images.json      |  199 +
 .../fixtures/profitbricks/list_images.xml       |   43 -
 .../fixtures/profitbricks/list_locations.json   |   43 +
 .../fixtures/profitbricks/list_nodes.json       |  169 +
 .../fixtures/profitbricks/list_nodes.xml        |  172 -
 .../fixtures/profitbricks/list_snapshots.json   |   37 +
 .../fixtures/profitbricks/list_volumes.json     |  112 +
 .../fixtures/profitbricks/list_volumes.xml      |   66 -
 .../fixtures/profitbricks/reboot_node.xml       |   10 -
 libcloud/test/compute/test_azure_arm.py         |   69 +
 libcloud/test/compute/test_ecs.py               |   12 +-
 libcloud/test/compute/test_profitbricks.py      | 5377 ++++++++++++++++--
 .../alb/describe_load_balancer_listeters.xml    |   27 +
 .../alb/describe_load_balancer_rules.xml        |   21 +
 .../describe_load_balancer_target_groups.xml    |   29 +
 .../fixtures/alb/describe_load_balancers.xml    |   31 +
 .../loadbalancer/fixtures/alb/describe_tags.xml |   18 +
 .../fixtures/alb/describe_target_health.xml     |   19 +
 libcloud/test/loadbalancer/test_alb.py          |  159 +
 libcloud/test/secrets.py-dist                   |    1 +
 121 files changed, 13645 insertions(+), 1931 deletions(-)
----------------------------------------------------------------------



[26/40] libcloud git commit: remove strictversion imported but unused

Posted by an...@apache.org.
remove strictversion imported but unused


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

Branch: refs/heads/trunk
Commit: ab681f6199008bc2f8c743127742d1f570678db1
Parents: aeb03d8
Author: Samuel Chong <sa...@gmail.com>
Authored: Mon Nov 21 14:12:25 2016 +1100
Committer: Samuel Chong <sa...@gmail.com>
Committed: Mon Nov 21 14:12:25 2016 +1100

----------------------------------------------------------------------
 libcloud/common/dimensiondata.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/libcloud/blob/ab681f61/libcloud/common/dimensiondata.py
----------------------------------------------------------------------
diff --git a/libcloud/common/dimensiondata.py b/libcloud/common/dimensiondata.py
index 3cb9f66..fdc3230 100644
--- a/libcloud/common/dimensiondata.py
+++ b/libcloud/common/dimensiondata.py
@@ -17,7 +17,7 @@ Dimension Data Common Components
 """
 from base64 import b64encode
 from time import sleep
-from distutils.version import LooseVersion, StrictVersion
+from distutils.version import LooseVersion
 from libcloud.utils.py3 import httplib
 from libcloud.utils.py3 import b
 from libcloud.common.base import ConnectionUserAndKey, XmlResponse, RawResponse


[09/40] libcloud git commit: Remove commented line

Posted by an...@apache.org.
Remove commented line


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

Branch: refs/heads/trunk
Commit: 53c6c9795c8c1e6e90d8c1bee216e14c14e68b70
Parents: 9cb7785
Author: Samuel Chong <sa...@gmail.com>
Authored: Wed Nov 9 13:41:11 2016 +1100
Committer: Samuel Chong <sa...@gmail.com>
Committed: Wed Nov 9 13:41:11 2016 +1100

----------------------------------------------------------------------
 libcloud/compute/drivers/dimensiondata.py | 10 +---------
 1 file changed, 1 insertion(+), 9 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/libcloud/blob/53c6c979/libcloud/compute/drivers/dimensiondata.py
----------------------------------------------------------------------
diff --git a/libcloud/compute/drivers/dimensiondata.py b/libcloud/compute/drivers/dimensiondata.py
index b0a5959..c295c94 100644
--- a/libcloud/compute/drivers/dimensiondata.py
+++ b/libcloud/compute/drivers/dimensiondata.py
@@ -800,20 +800,12 @@ class DimensionDataNodeDriver(NodeDriver):
         if location is not None:
             params['datacenterId'] = self._location_to_location_id(location)
 
-        # return self._to_images(
-        #     self.connection.request_with_orgId_api_2(
-        #         'image/osImage',
-        #         params=params)
-        #     .object)
-
-        images = self._to_images(
+        return self._to_images(
             self.connection.request_with_orgId_api_2(
                 'image/osImage',
                 params=params)
             .object)
 
-        return images
-
     def list_sizes(self, location=None):
         """
         return a list of available sizes


[11/40] libcloud git commit: Clone Image and Import Image features

Posted by an...@apache.org.
Clone Image and Import Image features


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

Branch: refs/heads/trunk
Commit: 125212068a0bc83b74815a8d20ae18f031674a5b
Parents: 2b97294
Author: Samuel Chong <sa...@gmail.com>
Authored: Mon Nov 14 15:16:20 2016 +1100
Committer: Samuel Chong <sa...@gmail.com>
Committed: Mon Nov 14 15:16:20 2016 +1100

----------------------------------------------------------------------
 libcloud/compute/drivers/dimensiondata.py | 148 ++++++++++++++++++++++---
 1 file changed, 132 insertions(+), 16 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/libcloud/blob/12521206/libcloud/compute/drivers/dimensiondata.py
----------------------------------------------------------------------
diff --git a/libcloud/compute/drivers/dimensiondata.py b/libcloud/compute/drivers/dimensiondata.py
index c295c94..d869e0a 100644
--- a/libcloud/compute/drivers/dimensiondata.py
+++ b/libcloud/compute/drivers/dimensiondata.py
@@ -2407,7 +2407,10 @@ class DimensionDataNodeDriver(NodeDriver):
         response_code = findtext(result, 'responseCode', TYPES_URN)
         return response_code in ['IN_PROGRESS', 'OK']
 
-    def ex_clone_node_to_image(self, node, image_name, image_description=None):
+    def ex_clone_node_to_image(self, node, image_name,
+                               image_description=None,
+                               cluster_id=None, is_guest_Os_Customization=None,
+                               tag_key_id=None, tag_value=None):
         """
         Clone a server into a customer image.
 
@@ -2424,10 +2427,53 @@ class DimensionDataNodeDriver(NodeDriver):
         """
         if image_description is None:
             image_description = ''
-        result = self.connection.request_with_orgId_api_1(
-            'server/%s?clone=%s&desc=%s' %
-            (node.id, image_name, image_description)).object
-        response_code = findtext(result, 'result', GENERAL_NS)
+
+        node_id = self._node_to_node_id(node)
+
+        # Version 2.3 and lower
+        if float(self.connection.active_api_version) < 2.4:
+            response = self.connection.request_with_orgId_api_1(
+                'server/%s?clone=%s&desc=%s' %
+                (node_id, image_name, image_description)).object
+
+        # Version 2.4 and higher
+        else:
+            clone_server_elem = ET.Element('cloneServer',
+                                             {'id': node_id,
+                                              'xmlns': TYPES_URN})
+
+            ET.SubElement(clone_server_elem, 'imageName').text = image_name
+
+            if image_description is not None:
+                ET.SubElement(clone_server_elem, 'description').text = \
+                    image_description
+
+            if cluster_id is not None:
+                ET.SubElement(clone_server_elem, 'clusterId').text = \
+                    cluster_id
+
+            if is_guest_Os_Customization is not None:
+                ET.SubElement(clone_server_elem, 'guestOsCustomization')\
+                    .text = is_guest_Os_Customization
+
+            if tag_key_id is not None:
+                tag_elem = ET.SubElement(clone_server_elem, 'tagById')
+                ET.SubElement(tag_elem, 'tagKeyId').text = tag_key_id
+
+                if tag_value is not None:
+                    ET.SubElement(tag_elem, 'value').text = tag_value
+
+            response = self.connection.request_with_orgId_api_2(
+                'server/cloneServer',
+                method='POST',
+                data=ET.tostring(clone_server_elem)).object
+
+        # Version 2.3 and lower
+        if float(self.connection.active_api_version) < 2.4:
+            response_code = findtext(response, 'result', GENERAL_NS)
+        else:
+            response_code = findtext(response, 'responseCode', TYPES_URN)
+
         return response_code in ['IN_PROGRESS', 'SUCCESS']
 
     def ex_clean_failed_deployment(self, node):
@@ -3577,6 +3623,70 @@ class DimensionDataNodeDriver(NodeDriver):
         response_code = findtext(response, 'responseCode', TYPES_URN)
         return response_code in ['IN_PROGRESS', 'OK']
 
+    def import_image(self, ovf_package_name, name,
+                     cluster_id, description=None,
+                     is_guest_os_customization=None,
+                     tagkey_name_value_dictionaries=None):
+        # Unsupported for version lower than 2.4
+        if float(self.connection.active_api_version) < 2.4:
+            raise Exception("import image is feature is NOT supported in  " \
+                            "api version earlier than 2.4")
+        else:
+            import_image_elem = ET.Element(
+                'urn:importImage',
+                {
+                    'xmlns:urn': TYPES_URN,
+                })
+
+            ET.SubElement(
+                import_image_elem,
+                'urn:ovfPackage'
+            ).text = ovf_package_name
+
+            ET.SubElement(
+                import_image_elem,
+                'urn:name'
+            ).text = name
+
+            if description is not None:
+                ET.SubElement(
+                    import_image_elem,
+                    'urn:description'
+                ).text = description
+
+            ET.SubElement(
+                import_image_elem,
+                'urn:clusterId'
+            ).text = cluster_id
+
+            if is_guest_os_customization is not None:
+                ET.SubElement(
+                    import_image_elem,
+                    'urn:guestOsCustomization'
+                ).text = is_guest_os_customization
+
+            if len(tagkey_name_value_dictionaries) > 0:
+                for k, v in tagkey_name_value_dictionaries.items():
+                    print(k, v)
+                    tag_elem = ET.SubElement(
+                        import_image_elem,
+                        'urn:tag')
+                    ET.SubElement(tag_elem,
+                                  'urn:tagKeyName').text = k
+
+                    if v is not None:
+                        ET.SubElement(tag_elem,
+                                      'urn:value').text = v
+
+        response = self.connection.request_with_orgId_api_2(
+            'image/importImage',
+            method='POST',
+            data=ET.tostring(import_image_elem)).object
+
+        response_code = findtext(response, 'responseCode', TYPES_URN)
+        return response_code in ['IN_PROGRESS', 'OK']
+
+
     def _format_csv(self, http_response):
         text = http_response.read()
         lines = str.splitlines(ensure_string(text))
@@ -3940,8 +4050,20 @@ class DimensionDataNodeDriver(NodeDriver):
             = element.find(fixxpath('networkInfo', TYPES_URN)) is not None
         cpu_spec = self._to_cpu_spec(element.find(fixxpath('cpu', TYPES_URN)))
         disks = self._to_disks(element)
-        vmware_tools = self._to_vmware_tools(
-            element.find(fixxpath('vmwareTools', TYPES_URN)))
+
+        # Version 2.3 or earlier
+        if float(self.connection.active_api_version) < 2.4:
+            vmware_tools = self._to_vmware_tools(
+                element.find(fixxpath('vmwareTools', TYPES_URN)))
+            operation_system = element.find(fixxpath(
+                'operatingSystem', TYPES_URN))
+        else:
+            vmware_tools = self._to_vmware_tools(
+                element.find(fixxpath('guest/vmTools', TYPES_URN)))
+
+            operation_system = element.find(fixxpath(
+                'guest/operatingSystem', TYPES_URN))
+
         extra = {
             'description': findtext(element, 'description', TYPES_URN),
             'sourceImageId': findtext(element, 'sourceImageId', TYPES_URN),
@@ -3957,15 +4079,9 @@ class DimensionDataNodeDriver(NodeDriver):
                 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'),
+            'OS_id': operation_system.get('id'),
+            'OS_type': operation_system.get('family'),
+            'OS_displayName': operation_system.get('displayName'),
             'status': status,
             'disks': disks,
             'vmWareTools': vmware_tools


[30/40] libcloud git commit: Replace Distutils.version LooseVersion with a customised version. Temp workaround until Travis CI support Distutils.version with pylint

Posted by an...@apache.org.
Replace Distutils.version LooseVersion with a customised version. Temp workaround until Travis CI support Distutils.version with pylint


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

Branch: refs/heads/trunk
Commit: 13eee8a4e71d6f1c7ba3fd142bd4aedbe77f2085
Parents: d8cdb92
Author: Samuel Chong <sa...@gmail.com>
Authored: Thu Nov 24 12:28:04 2016 +1100
Committer: Samuel Chong <sa...@gmail.com>
Committed: Thu Nov 24 12:28:04 2016 +1100

----------------------------------------------------------------------
 libcloud/common/dimensiondata.py | 15 +++++++++------
 1 file changed, 9 insertions(+), 6 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/libcloud/blob/13eee8a4/libcloud/common/dimensiondata.py
----------------------------------------------------------------------
diff --git a/libcloud/common/dimensiondata.py b/libcloud/common/dimensiondata.py
index 0cb726f..a8f5917 100644
--- a/libcloud/common/dimensiondata.py
+++ b/libcloud/common/dimensiondata.py
@@ -17,18 +17,15 @@ Dimension Data Common Components
 """
 from base64 import b64encode
 from time import sleep
-
-try:
-    from distutils.version import LooseVersion  # pylint: disable=import-error
-except ImportError:
-    pass
-
+# TODO: use disutils.version when Travis CI fixed the pylint issue with version
+# from distutils.version import LooseVersion
 from libcloud.utils.py3 import httplib
 from libcloud.utils.py3 import b
 from libcloud.common.base import ConnectionUserAndKey, XmlResponse, RawResponse
 from libcloud.compute.base import Node
 from libcloud.utils.py3 import basestring
 from libcloud.utils.xml import findtext
+from libcloud.compute.types import LibcloudError, InvalidCredsError
 
 # Roadmap / TODO:
 #
@@ -318,6 +315,12 @@ def dd_object_to_id(obj, obj_type, id_value='id'):
         )
 
 
+# TODO: use disutils.version when Travis CI fixed the pylint issue with version
+#       This is a temporary workaround.
+def LooseVersion(version):
+    return float(version)
+
+
 class NetworkDomainServicePlan(object):
     ESSENTIALS = "ESSENTIALS"
     ADVANCED = "ADVANCED"


[23/40] libcloud git commit: Add feature exchange nic vlans

Posted by an...@apache.org.
Add feature exchange nic vlans


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

Branch: refs/heads/trunk
Commit: 8404532020b576651d3f915a157a707bd966d56c
Parents: 4189872
Author: Samuel Chong <sa...@gmail.com>
Authored: Thu Nov 17 11:54:34 2016 +1100
Committer: Samuel Chong <sa...@gmail.com>
Committed: Thu Nov 17 11:54:34 2016 +1100

----------------------------------------------------------------------
 libcloud/compute/drivers/dimensiondata.py       | 30 ++++++++++++++++++++
 .../2.4/exchange_nic_vlans_response.xml         |  8 ++++++
 .../test/compute/test_dimensiondata_v2_4.py     | 13 +++++++++
 3 files changed, 51 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/libcloud/blob/84045320/libcloud/compute/drivers/dimensiondata.py
----------------------------------------------------------------------
diff --git a/libcloud/compute/drivers/dimensiondata.py b/libcloud/compute/drivers/dimensiondata.py
index 60056b4..6f0a197 100644
--- a/libcloud/compute/drivers/dimensiondata.py
+++ b/libcloud/compute/drivers/dimensiondata.py
@@ -3690,6 +3690,36 @@ class DimensionDataNodeDriver(NodeDriver):
         response_code = findtext(response, 'responseCode', TYPES_URN)
         return response_code in ['IN_PROGRESS', 'OK']
 
+    def ex_exchange_nic_vlans(self, nic_id_1, nic_id_2):
+        """
+        Exchange NIC Vlans
+
+        :param    nic_id_1:  Nic ID 1
+        :type     nic_id_1: :``str``
+
+        :param    nic_id_2:  Nic ID 2
+        :type     nic_id_2: :``str``
+
+        :rtype: ``bool``
+        """
+
+        exchange_elem = ET.Element(
+            'urn:exchangeNicVlans',
+            {
+                'xmlns:urn': TYPES_URN,
+            })
+
+        ET.SubElement(exchange_elem, 'urn:nicId1').text = nic_id_1
+        ET.SubElement(exchange_elem, 'urn:nicId2').text = nic_id_2
+
+        response = self.connection.request_with_orgId_api_2(
+            'server/exchangeNicVlans',
+            method='POST',
+            data=ET.tostring(exchange_elem)).object
+
+        response_code = findtext(response, 'responseCode', TYPES_URN)
+        return response_code in ['IN_PROGRESS', 'OK']
+
     def _format_csv(self, http_response):
         text = http_response.read()
         lines = str.splitlines(ensure_string(text))

http://git-wip-us.apache.org/repos/asf/libcloud/blob/84045320/libcloud/test/compute/fixtures/dimensiondata/2.4/exchange_nic_vlans_response.xml
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/dimensiondata/2.4/exchange_nic_vlans_response.xml b/libcloud/test/compute/fixtures/dimensiondata/2.4/exchange_nic_vlans_response.xml
new file mode 100644
index 0000000..d0e8315
--- /dev/null
+++ b/libcloud/test/compute/fixtures/dimensiondata/2.4/exchange_nic_vlans_response.xml
@@ -0,0 +1,8 @@
+<urn:response requestId="na/2015-01-18T13:37:20/62f06368-c3fb-11e3-b29c-001517c4643e"
+xmlns:urn="urn:didata.com:api:cloud:types">
+    <urn:operation>EXCHANGE_NIC_VLANS</urn:operation>
+    <urn:responseCode>OK</urn:responseCode>
+    <urn:message>Request to exchange VLANs for Server with Id
+'1cec8cfb-69e7-4de9-8404-debf116f5242' has been accepted and is being
+processed.</urn:message>
+</urn:response>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/libcloud/blob/84045320/libcloud/test/compute/test_dimensiondata_v2_4.py
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/test_dimensiondata_v2_4.py b/libcloud/test/compute/test_dimensiondata_v2_4.py
index 7a2ba63..d835b5c 100644
--- a/libcloud/test/compute/test_dimensiondata_v2_4.py
+++ b/libcloud/test/compute/test_dimensiondata_v2_4.py
@@ -2039,6 +2039,12 @@ class DimensionData_v2_4_Tests(unittest.TestCase, TestCaseMixin):
             tagkey_name_value_dictionaries=tag_dictionaries)
         self.assertTrue(success)
 
+    def test_exchange_nic_vlans(self):
+        success = self.driver.ex_exchange_nic_vlans(
+                  nic_id_1='a4b4b42b-ccb5-416f-b052-ce7cb7fdff12',
+                  nic_id_2='b39d09b8-ea65-424a-8fa6-c6f5a98afc69')
+        self.assertTrue(success)
+
 class InvalidRequestError(Exception):
     def __init__(self, tag):
         super(InvalidRequestError, self).__init__("Invalid Request - %s" % tag)
@@ -3302,5 +3308,12 @@ class DimensionDataMockHttp(StorageMockHttp, MockHttp):
         )
         return httplib.OK, body, {}, httplib.responses[httplib.OK]
 
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_exchangeNicVlans(
+        self, method, url, body, headers):
+        body = self.fixtures.load(
+            '2.4/exchange_nic_vlans_response.xml'
+        )
+        return httplib.OK, body, {}, httplib.responses[httplib.OK]
+
 if __name__ == '__main__':
     sys.exit(unittest.main())


[17/40] libcloud git commit: Unit tests for 2.3

Posted by an...@apache.org.
http://git-wip-us.apache.org/repos/asf/libcloud/blob/bb1b8104/libcloud/test/compute/test_dimensiondata.py
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/test_dimensiondata.py b/libcloud/test/compute/test_dimensiondata.py
deleted file mode 100644
index bf121b5..0000000
--- a/libcloud/test/compute/test_dimensiondata.py
+++ /dev/null
@@ -1,3281 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License.  You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-try:
-    from lxml import etree as ET
-except ImportError:
-    from xml.etree import ElementTree as ET
-
-import sys
-from types import GeneratorType
-from libcloud.utils.py3 import httplib
-
-from libcloud.common.types import InvalidCredsError
-from libcloud.common.dimensiondata import DimensionDataAPIException, NetworkDomainServicePlan
-from libcloud.common.dimensiondata import DimensionDataServerCpuSpecification, DimensionDataServerDisk, DimensionDataServerVMWareTools
-from libcloud.common.dimensiondata import DimensionDataTag, DimensionDataTagKey
-from libcloud.common.dimensiondata import DimensionDataIpAddress, \
-    DimensionDataIpAddressList, DimensionDataChildIpAddressList, \
-    DimensionDataPortList, DimensionDataPort, DimensionDataChildPortList
-from libcloud.common.dimensiondata import TYPES_URN
-from libcloud.compute.drivers.dimensiondata import DimensionDataNodeDriver as DimensionData
-from libcloud.compute.drivers.dimensiondata import DimensionDataNic
-from libcloud.compute.base import Node, NodeAuthPassword, NodeLocation
-from libcloud.test import MockHttp, unittest, MockRawResponse, StorageMockHttp
-from libcloud.test.compute import TestCaseMixin
-from libcloud.test.file_fixtures import ComputeFileFixtures
-from libcloud.test.secrets import DIMENSIONDATA_PARAMS
-from libcloud.utils.xml import fixxpath, findtext, findall
-
-
-class DimensionDataTests(unittest.TestCase, TestCaseMixin):
-
-    def setUp(self):
-        DimensionData.connectionCls.conn_classes = (None, DimensionDataMockHttp)
-        DimensionData.connectionCls.rawResponseCls = \
-            DimensionDataMockRawResponse
-        DimensionDataMockHttp.type = None
-        self.driver = DimensionData(*DIMENSIONDATA_PARAMS)
-
-    def test_invalid_region(self):
-        with self.assertRaises(ValueError):
-            DimensionData(*DIMENSIONDATA_PARAMS, region='blah')
-
-    def test_invalid_creds(self):
-        DimensionDataMockHttp.type = 'UNAUTHORIZED'
-        with self.assertRaises(InvalidCredsError):
-            self.driver.list_nodes()
-
-    def test_get_account_details(self):
-        DimensionDataMockHttp.type = None
-        ret = self.driver.connection.get_account_details()
-        self.assertEqual(ret.full_name, 'Test User')
-        self.assertEqual(ret.first_name, 'Test')
-        self.assertEqual(ret.email, 'test@example.com')
-
-    def test_list_locations_response(self):
-        DimensionDataMockHttp.type = None
-        ret = self.driver.list_locations()
-        self.assertEqual(len(ret), 5)
-        first_loc = ret[0]
-        self.assertEqual(first_loc.id, 'NA3')
-        self.assertEqual(first_loc.name, 'US - West')
-        self.assertEqual(first_loc.country, 'US')
-
-    def test_list_nodes_response(self):
-        DimensionDataMockHttp.type = None
-        ret = self.driver.list_nodes()
-        self.assertEqual(len(ret), 7)
-
-    def test_node_extras(self):
-        DimensionDataMockHttp.type = None
-        ret = self.driver.list_nodes()
-        self.assertTrue(isinstance(ret[0].extra['vmWareTools'], DimensionDataServerVMWareTools))
-        self.assertTrue(isinstance(ret[0].extra['cpu'], DimensionDataServerCpuSpecification))
-        self.assertTrue(isinstance(ret[0].extra['disks'], list))
-        self.assertTrue(isinstance(ret[0].extra['disks'][0], DimensionDataServerDisk))
-        self.assertEqual(ret[0].extra['disks'][0].size_gb, 10)
-        self.assertTrue(isinstance(ret[1].extra['disks'], list))
-        self.assertTrue(isinstance(ret[1].extra['disks'][0], DimensionDataServerDisk))
-        self.assertEqual(ret[1].extra['disks'][0].size_gb, 10)
-
-    def test_server_states(self):
-        DimensionDataMockHttp.type = None
-        ret = self.driver.list_nodes()
-        self.assertTrue(ret[0].state == 'running')
-        self.assertTrue(ret[1].state == 'starting')
-        self.assertTrue(ret[2].state == 'stopping')
-        self.assertTrue(ret[3].state == 'reconfiguring')
-        self.assertTrue(ret[4].state == 'running')
-        self.assertTrue(ret[5].state == 'terminated')
-        self.assertTrue(ret[6].state == 'stopped')
-        self.assertEqual(len(ret), 7)
-
-    def test_list_nodes_response_PAGINATED(self):
-        DimensionDataMockHttp.type = 'PAGINATED'
-        ret = self.driver.list_nodes()
-        self.assertEqual(len(ret), 9)
-
-    def test_paginated_mcp2_call_EMPTY(self):
-        # cache org
-        self.driver.connection._get_orgId()
-        DimensionDataMockHttp.type = 'EMPTY'
-        node_list_generator = self.driver.connection.paginated_request_with_orgId_api_2('server/server')
-        empty_node_list = []
-        for node_list in node_list_generator:
-            empty_node_list.extend(node_list)
-        self.assertTrue(len(empty_node_list) == 0)
-
-    def test_paginated_mcp2_call_PAGED_THEN_EMPTY(self):
-        # cache org
-        self.driver.connection._get_orgId()
-        DimensionDataMockHttp.type = 'PAGED_THEN_EMPTY'
-        node_list_generator = self.driver.connection.paginated_request_with_orgId_api_2('server/server')
-        final_node_list = []
-        for node_list in node_list_generator:
-            final_node_list.extend(node_list)
-        self.assertTrue(len(final_node_list) == 2)
-
-    def test_paginated_mcp2_call_with_page_size(self):
-        # cache org
-        self.driver.connection._get_orgId()
-        DimensionDataMockHttp.type = 'PAGESIZE50'
-        node_list_generator = self.driver.connection.paginated_request_with_orgId_api_2('server/server', page_size=50)
-        self.assertTrue(isinstance(node_list_generator, GeneratorType))
-
-    # We're making sure here the filters make it to the URL
-    # See  _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_server_ALLFILTERS for asserts
-    def test_list_nodes_response_strings_ALLFILTERS(self):
-        DimensionDataMockHttp.type = 'ALLFILTERS'
-        ret = self.driver.list_nodes(ex_location='fake_loc', ex_name='fake_name',
-                                     ex_ipv6='fake_ipv6', ex_ipv4='fake_ipv4', ex_vlan='fake_vlan',
-                                     ex_image='fake_image', ex_deployed=True,
-                                     ex_started=True, ex_state='fake_state',
-                                     ex_network='fake_network', ex_network_domain='fake_network_domain')
-        self.assertTrue(isinstance(ret, list))
-        self.assertEqual(len(ret), 7)
-
-        node = ret[3]
-        self.assertTrue(isinstance(node.extra['disks'], list))
-        self.assertTrue(isinstance(node.extra['disks'][0], DimensionDataServerDisk))
-        self.assertEqual(node.size.id, '1')
-        self.assertEqual(node.image.id, '3ebf3c0f-90fe-4a8b-8585-6e65b316592c')
-        self.assertEqual(node.image.name, 'WIN2008S/32')
-        disk = node.extra['disks'][0]
-        self.assertEqual(disk.id, "c2e1f199-116e-4dbc-9960-68720b832b0a")
-        self.assertEqual(disk.scsi_id, 0)
-        self.assertEqual(disk.size_gb, 50)
-        self.assertEqual(disk.speed, "STANDARD")
-        self.assertEqual(disk.state, "NORMAL")
-
-    def test_list_nodes_response_LOCATION(self):
-        DimensionDataMockHttp.type = None
-        ret = self.driver.list_locations()
-        first_loc = ret[0]
-        ret = self.driver.list_nodes(ex_location=first_loc)
-        for node in ret:
-            self.assertEqual(node.extra['datacenterId'], 'NA3')
-
-    def test_list_nodes_response_LOCATION_STR(self):
-        DimensionDataMockHttp.type = None
-        ret = self.driver.list_nodes(ex_location='NA3')
-        for node in ret:
-            self.assertEqual(node.extra['datacenterId'], 'NA3')
-
-    def test_list_sizes_response(self):
-        DimensionDataMockHttp.type = None
-        ret = self.driver.list_sizes()
-        self.assertEqual(len(ret), 1)
-        size = ret[0]
-        self.assertEqual(size.name, 'default')
-
-    def test_reboot_node_response(self):
-        node = Node(id='11', name=None, state=None,
-                    public_ips=None, private_ips=None, driver=self.driver)
-        ret = node.reboot()
-        self.assertTrue(ret is True)
-
-    def test_reboot_node_response_INPROGRESS(self):
-        DimensionDataMockHttp.type = 'INPROGRESS'
-        node = Node(id='11', name=None, state=None,
-                    public_ips=None, private_ips=None, driver=self.driver)
-        with self.assertRaises(DimensionDataAPIException):
-            node.reboot()
-
-    def test_destroy_node_response(self):
-        node = Node(id='11', name=None, state=None,
-                    public_ips=None, private_ips=None, driver=self.driver)
-        ret = node.destroy()
-        self.assertTrue(ret is True)
-
-    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)
-        with self.assertRaises(DimensionDataAPIException):
-            node.destroy()
-
-    def test_list_images(self):
-        images = self.driver.list_images()
-        self.assertEqual(len(images), 3)
-        self.assertEqual(images[0].name, 'RedHat 6 64-bit 2 CPU')
-        self.assertEqual(images[0].id, 'c14b1a46-2428-44c1-9c1a-b20e6418d08c')
-        self.assertEqual(images[0].extra['location'].id, 'NA9')
-        self.assertEqual(images[0].extra['cpu'].cpu_count, 2)
-        self.assertEqual(images[0].extra['OS_displayName'], 'REDHAT6/64')
-
-    def test_clean_failed_deployment_response_with_node(self):
-        node = Node(id='11', name=None, state=None,
-                    public_ips=None, private_ips=None, driver=self.driver)
-        ret = self.driver.ex_clean_failed_deployment(node)
-        self.assertTrue(ret is True)
-
-    def test_clean_failed_deployment_response_with_node_id(self):
-        node = 'e75ead52-692f-4314-8725-c8a4f4d13a87'
-        ret = self.driver.ex_clean_failed_deployment(node)
-        self.assertTrue(ret is True)
-
-    def test_ex_list_customer_images(self):
-        images = self.driver.ex_list_customer_images()
-        self.assertEqual(len(images), 3)
-        self.assertEqual(images[0].name, 'ImportedCustomerImage')
-        self.assertEqual(images[0].id, '5234e5c7-01de-4411-8b6e-baeb8d91cf5d')
-        self.assertEqual(images[0].extra['location'].id, 'NA9')
-        self.assertEqual(images[0].extra['cpu'].cpu_count, 4)
-        self.assertEqual(images[0].extra['OS_displayName'], 'REDHAT6/64')
-
-    def test_create_mcp1_node_optional_param(self):
-        root_pw = NodeAuthPassword('pass123')
-        image = self.driver.list_images()[0]
-        network = self.driver.ex_list_networks()[0]
-        cpu_spec = DimensionDataServerCpuSpecification(cpu_count='4',
-                                                       cores_per_socket='2',
-                                                       performance='STANDARD')
-        disks = [DimensionDataServerDisk(scsi_id='0', speed='HIGHPERFORMANCE')]
-        node = self.driver.create_node(name='test2', image=image, auth=root_pw,
-                                       ex_description='test2 node',
-                                       ex_network=network,
-                                       ex_is_started=False,
-                                       ex_memory_gb=8,
-                                       ex_disks=disks,
-                                       ex_cpu_specification=cpu_spec,
-                                       ex_primary_dns='10.0.0.5',
-                                       ex_secondary_dns='10.0.0.6'
-                                       )
-        self.assertEqual(node.id, 'e75ead52-692f-4314-8725-c8a4f4d13a87')
-        self.assertEqual(node.extra['status'].action, 'DEPLOY_SERVER')
-
-    def test_create_mcp1_node_response_no_pass_random_gen(self):
-        image = self.driver.list_images()[0]
-        network = self.driver.ex_list_networks()[0]
-        node = self.driver.create_node(name='test2', image=image, auth=None,
-                                       ex_description='test2 node',
-                                       ex_network=network,
-                                       ex_is_started=False)
-        self.assertEqual(node.id, 'e75ead52-692f-4314-8725-c8a4f4d13a87')
-        self.assertEqual(node.extra['status'].action, 'DEPLOY_SERVER')
-        self.assertTrue('password' in node.extra)
-
-    def test_create_mcp1_node_response_no_pass_customer_windows(self):
-        image = self.driver.ex_list_customer_images()[1]
-        network = self.driver.ex_list_networks()[0]
-        node = self.driver.create_node(name='test2', image=image, auth=None,
-                                       ex_description='test2 node', ex_network=network,
-                                       ex_is_started=False)
-        self.assertEqual(node.id, 'e75ead52-692f-4314-8725-c8a4f4d13a87')
-        self.assertEqual(node.extra['status'].action, 'DEPLOY_SERVER')
-        self.assertTrue('password' in node.extra)
-
-    def test_create_mcp1_node_response_no_pass_customer_windows_STR(self):
-        image = self.driver.ex_list_customer_images()[1].id
-        network = self.driver.ex_list_networks()[0]
-        node = self.driver.create_node(name='test2', image=image, auth=None,
-                                       ex_description='test2 node', ex_network=network,
-                                       ex_is_started=False)
-        self.assertEqual(node.id, 'e75ead52-692f-4314-8725-c8a4f4d13a87')
-        self.assertEqual(node.extra['status'].action, 'DEPLOY_SERVER')
-        self.assertTrue('password' in node.extra)
-
-    def test_create_mcp1_node_response_no_pass_customer_linux(self):
-        image = self.driver.ex_list_customer_images()[0]
-        network = self.driver.ex_list_networks()[0]
-        node = self.driver.create_node(name='test2', image=image, auth=None,
-                                       ex_description='test2 node', ex_network=network,
-                                       ex_is_started=False)
-        self.assertEqual(node.id, 'e75ead52-692f-4314-8725-c8a4f4d13a87')
-        self.assertEqual(node.extra['status'].action, 'DEPLOY_SERVER')
-        self.assertTrue('password' not in node.extra)
-
-    def test_create_mcp1_node_response_no_pass_customer_linux_STR(self):
-        image = self.driver.ex_list_customer_images()[0].id
-        network = self.driver.ex_list_networks()[0]
-        node = self.driver.create_node(name='test2', image=image, auth=None,
-                                       ex_description='test2 node', ex_network=network,
-                                       ex_is_started=False)
-        self.assertEqual(node.id, 'e75ead52-692f-4314-8725-c8a4f4d13a87')
-        self.assertEqual(node.extra['status'].action, 'DEPLOY_SERVER')
-        self.assertTrue('password' not in node.extra)
-
-    def test_create_mcp1_node_response_STR(self):
-        rootPw = 'pass123'
-        image = self.driver.list_images()[0].id
-        network = self.driver.ex_list_networks()[0].id
-        node = self.driver.create_node(name='test2', image=image, auth=rootPw,
-                                       ex_description='test2 node', ex_network=network,
-                                       ex_is_started=False)
-        self.assertEqual(node.id, 'e75ead52-692f-4314-8725-c8a4f4d13a87')
-        self.assertEqual(node.extra['status'].action, 'DEPLOY_SERVER')
-
-    def test_create_node_response_network_domain(self):
-        rootPw = NodeAuthPassword('pass123')
-        location = self.driver.ex_get_location_by_id('NA9')
-        image = self.driver.list_images(location=location)[0]
-        network_domain = self.driver.ex_list_network_domains(location=location)[0]
-        vlan = self.driver.ex_list_vlans(location=location)[0]
-        cpu = DimensionDataServerCpuSpecification(
-            cpu_count=4,
-            cores_per_socket=1,
-            performance='HIGHPERFORMANCE'
-        )
-        node = self.driver.create_node(name='test2', image=image, auth=rootPw,
-                                       ex_description='test2 node',
-                                       ex_network_domain=network_domain,
-                                       ex_vlan=vlan,
-                                       ex_is_started=False, ex_cpu_specification=cpu,
-                                       ex_memory_gb=4)
-        self.assertEqual(node.id, 'e75ead52-692f-4314-8725-c8a4f4d13a87')
-        self.assertEqual(node.extra['status'].action, 'DEPLOY_SERVER')
-
-    def test_create_node_response_network_domain_STR(self):
-        rootPw = NodeAuthPassword('pass123')
-        location = self.driver.ex_get_location_by_id('NA9')
-        image = self.driver.list_images(location=location)[0]
-        network_domain = self.driver.ex_list_network_domains(location=location)[0].id
-        vlan = self.driver.ex_list_vlans(location=location)[0].id
-        cpu = DimensionDataServerCpuSpecification(
-            cpu_count=4,
-            cores_per_socket=1,
-            performance='HIGHPERFORMANCE'
-        )
-        node = self.driver.create_node(name='test2', image=image, auth=rootPw,
-                                       ex_description='test2 node',
-                                       ex_network_domain=network_domain,
-                                       ex_vlan=vlan,
-                                       ex_is_started=False, ex_cpu_specification=cpu,
-                                       ex_memory_gb=4)
-        self.assertEqual(node.id, 'e75ead52-692f-4314-8725-c8a4f4d13a87')
-        self.assertEqual(node.extra['status'].action, 'DEPLOY_SERVER')
-
-    def test_create_mcp1_node_no_network(self):
-        rootPw = NodeAuthPassword('pass123')
-        image = self.driver.list_images()[0]
-        with self.assertRaises(InvalidRequestError):
-            self.driver.create_node(name='test2',
-                                    image=image,
-                                    auth=rootPw,
-                                    ex_description='test2 node',
-                                    ex_network=None,
-                                    ex_is_started=False)
-
-    def test_create_node_mcp1_ipv4(self):
-        rootPw = NodeAuthPassword('pass123')
-        image = self.driver.list_images()[0]
-        node = self.driver.create_node(name='test2',
-                                       image=image,
-                                       auth=rootPw,
-                                       ex_description='test2 node',
-                                       ex_network='fakenetwork',
-                                       ex_primary_ipv4='10.0.0.1',
-                                       ex_is_started=False)
-        self.assertEqual(node.id, 'e75ead52-692f-4314-8725-c8a4f4d13a87')
-        self.assertEqual(node.extra['status'].action, 'DEPLOY_SERVER')
-
-    def test_create_node_mcp1_network(self):
-        rootPw = NodeAuthPassword('pass123')
-        image = self.driver.list_images()[0]
-        node = self.driver.create_node(name='test2',
-                                       image=image,
-                                       auth=rootPw,
-                                       ex_description='test2 node',
-                                       ex_network='fakenetwork',
-                                       ex_is_started=False)
-        self.assertEqual(node.id, 'e75ead52-692f-4314-8725-c8a4f4d13a87')
-        self.assertEqual(node.extra['status'].action, 'DEPLOY_SERVER')
-
-    def test_create_node_mcp2_vlan(self):
-        rootPw = NodeAuthPassword('pass123')
-        image = self.driver.list_images()[0]
-        node = self.driver.create_node(name='test2',
-                                       image=image,
-                                       auth=rootPw,
-                                       ex_description='test2 node',
-                                       ex_network_domain='fakenetworkdomain',
-                                       ex_vlan='fakevlan',
-                                       ex_is_started=False)
-        self.assertEqual(node.id, 'e75ead52-692f-4314-8725-c8a4f4d13a87')
-        self.assertEqual(node.extra['status'].action, 'DEPLOY_SERVER')
-
-    def test_create_node_mcp2_ipv4(self):
-        rootPw = NodeAuthPassword('pass123')
-        image = self.driver.list_images()[0]
-        node = self.driver.create_node(name='test2',
-                                       image=image,
-                                       auth=rootPw,
-                                       ex_description='test2 node',
-                                       ex_network_domain='fakenetworkdomain',
-                                       ex_primary_ipv4='10.0.0.1',
-                                       ex_is_started=False)
-        self.assertEqual(node.id, 'e75ead52-692f-4314-8725-c8a4f4d13a87')
-        self.assertEqual(node.extra['status'].action, 'DEPLOY_SERVER')
-
-    def test_create_node_network_domain_no_vlan_or_ipv4(self):
-        rootPw = NodeAuthPassword('pass123')
-        image = self.driver.list_images()[0]
-        with self.assertRaises(ValueError):
-            self.driver.create_node(name='test2',
-                                    image=image,
-                                    auth=rootPw,
-                                    ex_description='test2 node',
-                                    ex_network_domain='fake_network_domain',
-                                    ex_is_started=False)
-
-    def test_create_node_response(self):
-        rootPw = NodeAuthPassword('pass123')
-        image = self.driver.list_images()[0]
-        node = self.driver.create_node(
-            name='test3',
-            image=image,
-            auth=rootPw,
-            ex_network_domain='fakenetworkdomain',
-            ex_primary_nic_vlan='fakevlan'
-        )
-        self.assertEqual(node.id, 'e75ead52-692f-4314-8725-c8a4f4d13a87')
-        self.assertEqual(node.extra['status'].action, 'DEPLOY_SERVER')
-
-    def test_create_node_ms_time_zone(self):
-        rootPw = NodeAuthPassword('pass123')
-        image = self.driver.list_images()[0]
-        node = self.driver.create_node(
-            name='test3',
-            image=image,
-            auth=rootPw,
-            ex_network_domain='fakenetworkdomain',
-            ex_primary_nic_vlan='fakevlan',
-            ex_microsoft_time_zone='040'
-        )
-        self.assertEqual(node.id, 'e75ead52-692f-4314-8725-c8a4f4d13a87')
-        self.assertEqual(node.extra['status'].action, 'DEPLOY_SERVER')
-
-    def test_create_node_ambigious_mcps_fail(self):
-        rootPw = NodeAuthPassword('pass123')
-        image = self.driver.list_images()[0]
-        with self.assertRaises(ValueError):
-            self.driver.create_node(
-                name='test3',
-                image=image,
-                auth=rootPw,
-                ex_network_domain='fakenetworkdomain',
-                ex_network='fakenetwork',
-                ex_primary_nic_vlan='fakevlan'
-            )
-
-    def test_create_node_no_network_domain_fail(self):
-        rootPw = NodeAuthPassword('pass123')
-        image = self.driver.list_images()[0]
-        with self.assertRaises(ValueError):
-            self.driver.create_node(
-                name='test3',
-                image=image,
-                auth=rootPw,
-                ex_primary_nic_vlan='fakevlan'
-            )
-
-    def test_create_node_no_primary_nic_fail(self):
-        rootPw = NodeAuthPassword('pass123')
-        image = self.driver.list_images()[0]
-        with self.assertRaises(ValueError):
-            self.driver.create_node(
-                name='test3',
-                image=image,
-                auth=rootPw,
-                ex_network_domain='fakenetworkdomain'
-            )
-
-    def test_create_node_primary_vlan_nic(self):
-        rootPw = NodeAuthPassword('pass123')
-        image = self.driver.list_images()[0]
-        node = self.driver.create_node(
-            name='test3',
-            image=image,
-            auth=rootPw,
-            ex_network_domain='fakenetworkdomain',
-            ex_primary_nic_vlan='fakevlan',
-            ex_primary_nic_network_adapter='v1000'
-        )
-        self.assertEqual(node.id, 'e75ead52-692f-4314-8725-c8a4f4d13a87')
-        self.assertEqual(node.extra['status'].action, 'DEPLOY_SERVER')
-
-    def test_create_node_primary_ipv4(self):
-        rootPw = 'pass123'
-        image = self.driver.list_images()[0]
-        node = self.driver.create_node(
-            name='test3',
-            image=image,
-            auth=rootPw,
-            ex_network_domain='fakenetworkdomain',
-            ex_primary_nic_private_ipv4='10.0.0.1'
-        )
-        self.assertEqual(node.id, 'e75ead52-692f-4314-8725-c8a4f4d13a87')
-        self.assertEqual(node.extra['status'].action, 'DEPLOY_SERVER')
-
-    def test_create_node_both_primary_nic_and_vlan_fail(self):
-        rootPw = NodeAuthPassword('pass123')
-        image = self.driver.list_images()[0]
-        with self.assertRaises(ValueError):
-            self.driver.create_node(
-                name='test3',
-                image=image,
-                auth=rootPw,
-                ex_network_domain='fakenetworkdomain',
-                ex_primary_nic_private_ipv4='10.0.0.1',
-                ex_primary_nic_vlan='fakevlan'
-            )
-
-    def test_create_node_cpu_specification(self):
-        rootPw = NodeAuthPassword('pass123')
-        image = self.driver.list_images()[0]
-        cpu_spec = DimensionDataServerCpuSpecification(cpu_count='4',
-                                                       cores_per_socket='2',
-                                                       performance='STANDARD')
-        node = self.driver.create_node(name='test2',
-                                       image=image,
-                                       auth=rootPw,
-                                       ex_description='test2 node',
-                                       ex_network_domain='fakenetworkdomain',
-                                       ex_primary_nic_private_ipv4='10.0.0.1',
-                                       ex_is_started=False,
-                                       ex_cpu_specification=cpu_spec)
-        self.assertEqual(node.id, 'e75ead52-692f-4314-8725-c8a4f4d13a87')
-        self.assertEqual(node.extra['status'].action, 'DEPLOY_SERVER')
-
-    def test_create_node_memory(self):
-        rootPw = NodeAuthPassword('pass123')
-        image = self.driver.list_images()[0]
-
-        node = self.driver.create_node(name='test2',
-                                       image=image,
-                                       auth=rootPw,
-                                       ex_description='test2 node',
-                                       ex_network_domain='fakenetworkdomain',
-                                       ex_primary_nic_private_ipv4='10.0.0.1',
-                                       ex_is_started=False,
-                                       ex_memory_gb=8)
-        self.assertEqual(node.id, 'e75ead52-692f-4314-8725-c8a4f4d13a87')
-        self.assertEqual(node.extra['status'].action, 'DEPLOY_SERVER')
-
-    def test_create_node_disks(self):
-        rootPw = NodeAuthPassword('pass123')
-        image = self.driver.list_images()[0]
-        disks = [DimensionDataServerDisk(scsi_id='0', speed='HIGHPERFORMANCE')]
-        node = self.driver.create_node(name='test2',
-                                       image=image,
-                                       auth=rootPw,
-                                       ex_description='test2 node',
-                                       ex_network_domain='fakenetworkdomain',
-                                       ex_primary_nic_private_ipv4='10.0.0.1',
-                                       ex_is_started=False,
-                                       ex_disks=disks)
-        self.assertEqual(node.id, 'e75ead52-692f-4314-8725-c8a4f4d13a87')
-        self.assertEqual(node.extra['status'].action, 'DEPLOY_SERVER')
-
-    def test_create_node_disks_fail(self):
-        root_pw = NodeAuthPassword('pass123')
-        image = self.driver.list_images()[0]
-        disks = 'blah'
-        with self.assertRaises(TypeError):
-            self.driver.create_node(name='test2',
-                                    image=image,
-                                    auth=root_pw,
-                                    ex_description='test2 node',
-                                    ex_network_domain='fakenetworkdomain',
-                                    ex_primary_nic_private_ipv4='10.0.0.1',
-                                    ex_is_started=False,
-                                    ex_disks=disks)
-
-    def test_create_node_ipv4_gateway(self):
-        rootPw = NodeAuthPassword('pass123')
-        image = self.driver.list_images()[0]
-        node = self.driver.create_node(name='test2',
-                                       image=image,
-                                       auth=rootPw,
-                                       ex_description='test2 node',
-                                       ex_network_domain='fakenetworkdomain',
-                                       ex_primary_nic_private_ipv4='10.0.0.1',
-                                       ex_is_started=False,
-                                       ex_ipv4_gateway='10.2.2.2')
-        self.assertEqual(node.id, 'e75ead52-692f-4314-8725-c8a4f4d13a87')
-        self.assertEqual(node.extra['status'].action, 'DEPLOY_SERVER')
-
-    def test_create_node_network_domain_no_vlan_no_ipv4_fail(self):
-        rootPw = NodeAuthPassword('pass123')
-        image = self.driver.list_images()[0]
-        with self.assertRaises(ValueError):
-            self.driver.create_node(name='test2',
-                                    image=image,
-                                    auth=rootPw,
-                                    ex_description='test2 node',
-                                    ex_network_domain='fake_network_domain',
-                                    ex_is_started=False)
-
-    def test_create_node_mcp2_additional_nics_legacy(self):
-        rootPw = NodeAuthPassword('pass123')
-        image = self.driver.list_images()[0]
-        additional_vlans = ['fakevlan1', 'fakevlan2']
-        additional_ipv4 = ['10.0.0.2', '10.0.0.3']
-        node = self.driver.create_node(
-            name='test2',
-            image=image,
-            auth=rootPw,
-            ex_description='test2 node',
-            ex_network_domain='fakenetworkdomain',
-            ex_primary_ipv4='10.0.0.1',
-            ex_additional_nics_vlan=additional_vlans,
-            ex_additional_nics_ipv4=additional_ipv4,
-            ex_is_started=False)
-        self.assertEqual(node.id, 'e75ead52-692f-4314-8725-c8a4f4d13a87')
-        self.assertEqual(node.extra['status'].action, 'DEPLOY_SERVER')
-
-    def test_create_node_bad_additional_nics_ipv4(self):
-        rootPw = NodeAuthPassword('pass123')
-        image = self.driver.list_images()[0]
-        with self.assertRaises(TypeError):
-            self.driver.create_node(name='test2',
-                                    image=image,
-                                    auth=rootPw,
-                                    ex_description='test2 node',
-                                    ex_network_domain='fake_network_domain',
-                                    ex_vlan='fake_vlan',
-                                    ex_additional_nics_ipv4='badstring',
-                                    ex_is_started=False)
-
-    def test_create_node_additional_nics(self):
-        root_pw = NodeAuthPassword('pass123')
-        image = self.driver.list_images()[0]
-        nic1 = DimensionDataNic(vlan='fake_vlan',
-                                network_adapter_name='v1000')
-        nic2 = DimensionDataNic(private_ip_v4='10.1.1.2',
-                                network_adapter_name='v1000')
-        additional_nics = [nic1, nic2]
-
-        node = self.driver.create_node(name='test2',
-                                       image=image,
-                                       auth=root_pw,
-                                       ex_description='test2 node',
-                                       ex_network_domain='fakenetworkdomain',
-                                       ex_primary_nic_private_ipv4='10.0.0.1',
-                                       ex_additional_nics=additional_nics,
-                                       ex_is_started=False)
-
-        self.assertEqual(node.id, 'e75ead52-692f-4314-8725-c8a4f4d13a87')
-        self.assertEqual(node.extra['status'].action, 'DEPLOY_SERVER')
-
-    def test_create_node_additional_nics_vlan_ipv4_coexist_fail(self):
-        root_pw = NodeAuthPassword('pass123')
-        image = self.driver.list_images()[0]
-        nic1 = DimensionDataNic(private_ip_v4='10.1.1.1', vlan='fake_vlan',
-                                network_adapter_name='v1000')
-        nic2 = DimensionDataNic(private_ip_v4='10.1.1.2', vlan='fake_vlan2',
-                                network_adapter_name='v1000')
-        additional_nics = [nic1, nic2]
-        with self.assertRaises(ValueError):
-            self.driver.create_node(name='test2',
-                                    image=image,
-                                    auth=root_pw,
-                                    ex_description='test2 node',
-                                    ex_network_domain='fakenetworkdomain',
-                                    ex_primary_nic_private_ipv4='10.0.0.1',
-                                    ex_additional_nics=additional_nics,
-                                    ex_is_started=False
-                                    )
-
-    def test_create_node_additional_nics_invalid_input_fail(self):
-        root_pw = NodeAuthPassword('pass123')
-        image = self.driver.list_images()[0]
-        additional_nics = 'blah'
-        with self.assertRaises(TypeError):
-            self.driver.create_node(name='test2',
-                                    image=image,
-                                    auth=root_pw,
-                                    ex_description='test2 node',
-                                    ex_network_domain='fakenetworkdomain',
-                                    ex_primary_nic_private_ipv4='10.0.0.1',
-                                    ex_additional_nics=additional_nics,
-                                    ex_is_started=False
-                                    )
-
-    def test_create_node_additional_nics_vlan_ipv4_not_exist_fail(self):
-        root_pw = NodeAuthPassword('pass123')
-        image = self.driver.list_images()[0]
-        nic1 = DimensionDataNic(network_adapter_name='v1000')
-        nic2 = DimensionDataNic(network_adapter_name='v1000')
-        additional_nics = [nic1, nic2]
-        with self.assertRaises(ValueError):
-            self.driver.create_node(name='test2',
-                                    image=image,
-                                    auth=root_pw,
-                                    ex_description='test2 node',
-                                    ex_network_domain='fakenetworkdomain',
-                                    ex_primary_nic_private_ipv4='10.0.0.1',
-                                    ex_additional_nics=additional_nics,
-                                    ex_is_started=False)
-
-    def test_create_node_bad_additional_nics_vlan(self):
-        rootPw = NodeAuthPassword('pass123')
-        image = self.driver.list_images()[0]
-        with self.assertRaises(TypeError):
-            self.driver.create_node(name='test2',
-                                    image=image,
-                                    auth=rootPw,
-                                    ex_description='test2 node',
-                                    ex_network_domain='fake_network_domain',
-                                    ex_vlan='fake_vlan',
-                                    ex_additional_nics_vlan='badstring',
-                                    ex_is_started=False)
-
-    def test_create_node_mcp2_indicate_dns(self):
-        rootPw = NodeAuthPassword('pass123')
-        image = self.driver.list_images()[0]
-        node = self.driver.create_node(name='test2',
-                                       image=image,
-                                       auth=rootPw,
-                                       ex_description='test node dns',
-                                       ex_network_domain='fakenetworkdomain',
-                                       ex_primary_ipv4='10.0.0.1',
-                                       ex_primary_dns='8.8.8.8',
-                                       ex_secondary_dns='8.8.4.4',
-                                       ex_is_started=False)
-        self.assertEqual(node.id, 'e75ead52-692f-4314-8725-c8a4f4d13a87')
-        self.assertEqual(node.extra['status'].action, 'DEPLOY_SERVER')
-
-    def test_ex_shutdown_graceful(self):
-        node = Node(id='11', name=None, state=None,
-                    public_ips=None, private_ips=None, driver=self.driver)
-        ret = self.driver.ex_shutdown_graceful(node)
-        self.assertTrue(ret is True)
-
-    def test_ex_shutdown_graceful_INPROGRESS(self):
-        DimensionDataMockHttp.type = 'INPROGRESS'
-        node = Node(id='11', name=None, state=None,
-                    public_ips=None, private_ips=None, driver=self.driver)
-        with self.assertRaises(DimensionDataAPIException):
-            self.driver.ex_shutdown_graceful(node)
-
-    def test_ex_start_node(self):
-        node = Node(id='11', name=None, state=None,
-                    public_ips=None, private_ips=None, driver=self.driver)
-        ret = self.driver.ex_start_node(node)
-        self.assertTrue(ret is True)
-
-    def test_ex_start_node_INPROGRESS(self):
-        DimensionDataMockHttp.type = 'INPROGRESS'
-        node = Node(id='11', name=None, state=None,
-                    public_ips=None, private_ips=None, driver=self.driver)
-        with self.assertRaises(DimensionDataAPIException):
-            self.driver.ex_start_node(node)
-
-    def test_ex_power_off(self):
-        node = Node(id='11', name=None, state=None,
-                    public_ips=None, private_ips=None, driver=self.driver)
-        ret = self.driver.ex_power_off(node)
-        self.assertTrue(ret is True)
-
-    def test_ex_update_vm_tools(self):
-        node = Node(id='11', name=None, state=None,
-                    public_ips=None, private_ips=None, driver=self.driver)
-        ret = self.driver.ex_update_vm_tools(node)
-        self.assertTrue(ret is True)
-
-    def test_ex_power_off_INPROGRESS(self):
-        DimensionDataMockHttp.type = 'INPROGRESS'
-        node = Node(id='11', name=None, state='STOPPING',
-                    public_ips=None, private_ips=None, driver=self.driver)
-
-        with self.assertRaises(DimensionDataAPIException):
-            self.driver.ex_power_off(node)
-
-    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_attach_node_to_vlan(self):
-        node = self.driver.ex_get_node_by_id('e75ead52-692f-4314-8725-c8a4f4d13a87')
-        vlan = self.driver.ex_get_vlan('0e56433f-d808-4669-821d-812769517ff8')
-        ret = self.driver.ex_attach_node_to_vlan(node, vlan)
-        self.assertTrue(ret is True)
-
-    def test_ex_destroy_nic(self):
-        node = self.driver.ex_destroy_nic('a202e51b-41c0-4cfc-add0-b1c62fc0ecf6')
-        self.assertTrue(node)
-
-    def test_list_networks(self):
-        nets = self.driver.list_networks()
-        self.assertEqual(nets[0].name, 'test-net1')
-        self.assertTrue(isinstance(nets[0].location, NodeLocation))
-
-    def test_ex_create_network(self):
-        location = self.driver.ex_get_location_by_id('NA9')
-        net = self.driver.ex_create_network(location, "Test Network", "test")
-        self.assertEqual(net.id, "208e3a8e-9d2f-11e2-b29c-001517c4643e")
-        self.assertEqual(net.name, "Test Network")
-
-    def test_ex_create_network_NO_DESCRIPTION(self):
-        location = self.driver.ex_get_location_by_id('NA9')
-        net = self.driver.ex_create_network(location, "Test Network")
-        self.assertEqual(net.id, "208e3a8e-9d2f-11e2-b29c-001517c4643e")
-        self.assertEqual(net.name, "Test Network")
-
-    def test_ex_delete_network(self):
-        net = self.driver.ex_list_networks()[0]
-        result = self.driver.ex_delete_network(net)
-        self.assertTrue(result)
-
-    def test_ex_rename_network(self):
-        net = self.driver.ex_list_networks()[0]
-        result = self.driver.ex_rename_network(net, "barry")
-        self.assertTrue(result)
-
-    def test_ex_create_network_domain(self):
-        location = self.driver.ex_get_location_by_id('NA9')
-        plan = NetworkDomainServicePlan.ADVANCED
-        net = self.driver.ex_create_network_domain(location=location,
-                                                   name='test',
-                                                   description='test',
-                                                   service_plan=plan)
-        self.assertEqual(net.name, 'test')
-        self.assertTrue(net.id, 'f14a871f-9a25-470c-aef8-51e13202e1aa')
-
-    def test_ex_create_network_domain_NO_DESCRIPTION(self):
-        location = self.driver.ex_get_location_by_id('NA9')
-        plan = NetworkDomainServicePlan.ADVANCED
-        net = self.driver.ex_create_network_domain(location=location,
-                                                   name='test',
-                                                   service_plan=plan)
-        self.assertEqual(net.name, 'test')
-        self.assertTrue(net.id, 'f14a871f-9a25-470c-aef8-51e13202e1aa')
-
-    def test_ex_get_network_domain(self):
-        net = self.driver.ex_get_network_domain('8cdfd607-f429-4df6-9352-162cfc0891be')
-        self.assertEqual(net.id, '8cdfd607-f429-4df6-9352-162cfc0891be')
-        self.assertEqual(net.description, 'test2')
-        self.assertEqual(net.name, 'test')
-
-    def test_ex_update_network_domain(self):
-        net = self.driver.ex_get_network_domain('8cdfd607-f429-4df6-9352-162cfc0891be')
-        net.name = 'new name'
-        net2 = self.driver.ex_update_network_domain(net)
-        self.assertEqual(net2.name, 'new name')
-
-    def test_ex_delete_network_domain(self):
-        net = self.driver.ex_get_network_domain('8cdfd607-f429-4df6-9352-162cfc0891be')
-        result = self.driver.ex_delete_network_domain(net)
-        self.assertTrue(result)
-
-    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, 'Aurora')
-        self.assertTrue(isinstance(nets[0].location, NodeLocation))
-
-    def test_ex_list_network_domains_ALLFILTERS(self):
-        DimensionDataMockHttp.type = 'ALLFILTERS'
-        nets = self.driver.ex_list_network_domains(location='fake_location', name='fake_name',
-                                                   service_plan='fake_plan', state='fake_state')
-        self.assertEqual(nets[0].name, 'Aurora')
-        self.assertTrue(isinstance(nets[0].location, NodeLocation))
-
-    def test_ex_list_vlans(self):
-        vlans = self.driver.ex_list_vlans()
-        self.assertEqual(vlans[0].name, "Primary")
-
-    def test_ex_list_vlans_ALLFILTERS(self):
-        DimensionDataMockHttp.type = 'ALLFILTERS'
-        vlans = self.driver.ex_list_vlans(location='fake_location', network_domain='fake_network_domain',
-                                          name='fake_name', ipv4_address='fake_ipv4', ipv6_address='fake_ipv6', state='fake_state')
-        self.assertEqual(vlans[0].name, "Primary")
-
-    def test_ex_create_vlan(self,):
-        net = self.driver.ex_get_network_domain('8cdfd607-f429-4df6-9352-162cfc0891be')
-        vlan = self.driver.ex_create_vlan(network_domain=net,
-                                          name='test',
-                                          private_ipv4_base_address='10.3.4.0',
-                                          private_ipv4_prefix_size='24',
-                                          description='test vlan')
-        self.assertEqual(vlan.id, '0e56433f-d808-4669-821d-812769517ff8')
-
-    def test_ex_create_vlan_NO_DESCRIPTION(self,):
-        net = self.driver.ex_get_network_domain('8cdfd607-f429-4df6-9352-162cfc0891be')
-        vlan = self.driver.ex_create_vlan(network_domain=net,
-                                          name='test',
-                                          private_ipv4_base_address='10.3.4.0',
-                                          private_ipv4_prefix_size='24')
-        self.assertEqual(vlan.id, '0e56433f-d808-4669-821d-812769517ff8')
-
-    def test_ex_get_vlan(self):
-        vlan = self.driver.ex_get_vlan('0e56433f-d808-4669-821d-812769517ff8')
-        self.assertEqual(vlan.id, '0e56433f-d808-4669-821d-812769517ff8')
-        self.assertEqual(vlan.description, 'test2')
-        self.assertEqual(vlan.status, 'NORMAL')
-        self.assertEqual(vlan.name, 'Production VLAN')
-        self.assertEqual(vlan.private_ipv4_range_address, '10.0.3.0')
-        self.assertEqual(vlan.private_ipv4_range_size, 24)
-        self.assertEqual(vlan.ipv6_range_size, 64)
-        self.assertEqual(vlan.ipv6_range_address, '2607:f480:1111:1153:0:0:0:0')
-        self.assertEqual(vlan.ipv4_gateway, '10.0.3.1')
-        self.assertEqual(vlan.ipv6_gateway, '2607:f480:1111:1153:0:0:0:1')
-
-    def test_ex_wait_for_state(self):
-        self.driver.ex_wait_for_state('NORMAL',
-                                      self.driver.ex_get_vlan,
-                                      vlan_id='0e56433f-d808-4669-821d-812769517ff8')
-
-    def test_ex_wait_for_state_NODE(self):
-        self.driver.ex_wait_for_state('running',
-                                      self.driver.ex_get_node_by_id,
-                                      id='e75ead52-692f-4314-8725-c8a4f4d13a87')
-
-    def test_ex_wait_for_state_FAIL(self):
-        with self.assertRaises(DimensionDataAPIException) as context:
-            self.driver.ex_wait_for_state('starting',
-                                          self.driver.ex_get_node_by_id,
-                                          id='e75ead52-692f-4314-8725-c8a4f4d13a87',
-                                          timeout=2
-                                          )
-        self.assertEqual(context.exception.code, 'running')
-        self.assertTrue('timed out' in context.exception.msg)
-
-    def test_ex_update_vlan(self):
-        vlan = self.driver.ex_get_vlan('0e56433f-d808-4669-821d-812769517ff8')
-        vlan.name = 'new name'
-        vlan2 = self.driver.ex_update_vlan(vlan)
-        self.assertEqual(vlan2.name, 'new name')
-
-    def test_ex_delete_vlan(self):
-        vlan = self.driver.ex_get_vlan('0e56433f-d808-4669-821d-812769517ff8')
-        result = self.driver.ex_delete_vlan(vlan)
-        self.assertTrue(result)
-
-    def test_ex_expand_vlan(self):
-        vlan = self.driver.ex_get_vlan('0e56433f-d808-4669-821d-812769517ff8')
-        vlan.private_ipv4_range_size = '23'
-        vlan = self.driver.ex_expand_vlan(vlan)
-        self.assertEqual(vlan.private_ipv4_range_size, '23')
-
-    def test_ex_add_public_ip_block_to_network_domain(self):
-        net = self.driver.ex_get_network_domain('8cdfd607-f429-4df6-9352-162cfc0891be')
-        block = self.driver.ex_add_public_ip_block_to_network_domain(net)
-        self.assertEqual(block.id, '9945dc4a-bdce-11e4-8c14-b8ca3a5d9ef8')
-
-    def test_ex_list_public_ip_blocks(self):
-        net = self.driver.ex_get_network_domain('8cdfd607-f429-4df6-9352-162cfc0891be')
-        blocks = self.driver.ex_list_public_ip_blocks(net)
-        self.assertEqual(blocks[0].base_ip, '168.128.4.18')
-        self.assertEqual(blocks[0].size, '2')
-        self.assertEqual(blocks[0].id, '9945dc4a-bdce-11e4-8c14-b8ca3a5d9ef8')
-        self.assertEqual(blocks[0].location.id, 'NA9')
-        self.assertEqual(blocks[0].network_domain.id, net.id)
-
-    def test_ex_get_public_ip_block(self):
-        net = self.driver.ex_get_network_domain('8cdfd607-f429-4df6-9352-162cfc0891be')
-        block = self.driver.ex_get_public_ip_block('9945dc4a-bdce-11e4-8c14-b8ca3a5d9ef8')
-        self.assertEqual(block.base_ip, '168.128.4.18')
-        self.assertEqual(block.size, '2')
-        self.assertEqual(block.id, '9945dc4a-bdce-11e4-8c14-b8ca3a5d9ef8')
-        self.assertEqual(block.location.id, 'NA9')
-        self.assertEqual(block.network_domain.id, net.id)
-
-    def test_ex_delete_public_ip_block(self):
-        block = self.driver.ex_get_public_ip_block('9945dc4a-bdce-11e4-8c14-b8ca3a5d9ef8')
-        result = self.driver.ex_delete_public_ip_block(block)
-        self.assertTrue(result)
-
-    def test_ex_list_firewall_rules(self):
-        net = self.driver.ex_get_network_domain('8cdfd607-f429-4df6-9352-162cfc0891be')
-        rules = self.driver.ex_list_firewall_rules(net)
-        self.assertEqual(rules[0].id, '756cba02-b0bc-48f4-aea5-9445870b6148')
-        self.assertEqual(rules[0].network_domain.id, '8cdfd607-f429-4df6-9352-162cfc0891be')
-        self.assertEqual(rules[0].name, 'CCDEFAULT.BlockOutboundMailIPv4')
-        self.assertEqual(rules[0].action, 'DROP')
-        self.assertEqual(rules[0].ip_version, 'IPV4')
-        self.assertEqual(rules[0].protocol, 'TCP')
-        self.assertEqual(rules[0].source.ip_address, 'ANY')
-        self.assertTrue(rules[0].source.any_ip)
-        self.assertTrue(rules[0].destination.any_ip)
-
-    def test_ex_create_firewall_rule(self):
-        net = self.driver.ex_get_network_domain('8cdfd607-f429-4df6-9352-162cfc0891be')
-        rules = self.driver.ex_list_firewall_rules(net)
-        rule = self.driver.ex_create_firewall_rule(net, rules[0], 'FIRST')
-        self.assertEqual(rule.id, 'd0a20f59-77b9-4f28-a63b-e58496b73a6c')
-
-    def test_ex_create_firewall_rule_with_specific_source_ip(self):
-        net = self.driver.ex_get_network_domain('8cdfd607-f429-4df6-9352-162cfc0891be')
-        rules = self.driver.ex_list_firewall_rules(net)
-        specific_source_ip_rule = list(filter(lambda x: x.name == 'SpecificSourceIP',
-                                              rules))[0]
-        rule = self.driver.ex_create_firewall_rule(net, specific_source_ip_rule, 'FIRST')
-        self.assertEqual(rule.id, 'd0a20f59-77b9-4f28-a63b-e58496b73a6c')
-
-    def test_ex_create_firewall_rule_with_source_ip(self):
-        net = self.driver.ex_get_network_domain(
-            '8cdfd607-f429-4df6-9352-162cfc0891be')
-        rules = self.driver.ex_list_firewall_rules(net)
-        specific_source_ip_rule = \
-            list(filter(lambda x: x.name == 'SpecificSourceIP',
-                        rules))[0]
-        specific_source_ip_rule.source.any_ip = False
-        specific_source_ip_rule.source.ip_address = '10.0.0.1'
-        specific_source_ip_rule.source.ip_prefix_size = '15'
-        rule = self.driver.ex_create_firewall_rule(net,
-                                                   specific_source_ip_rule,
-                                                   'FIRST')
-        self.assertEqual(rule.id, 'd0a20f59-77b9-4f28-a63b-e58496b73a6c')
-
-    def test_ex_create_firewall_rule_with_any_ip(self):
-        net = self.driver.ex_get_network_domain(
-            '8cdfd607-f429-4df6-9352-162cfc0891be')
-        rules = self.driver.ex_list_firewall_rules(net)
-        specific_source_ip_rule = \
-            list(filter(lambda x: x.name == 'SpecificSourceIP',
-                        rules))[0]
-        specific_source_ip_rule.source.any_ip = True
-        rule = self.driver.ex_create_firewall_rule(net,
-                                                   specific_source_ip_rule,
-                                                   'FIRST')
-        self.assertEqual(rule.id, 'd0a20f59-77b9-4f28-a63b-e58496b73a6c')
-
-    def test_ex_create_firewall_rule_ip_prefix_size(self):
-        net = self.driver.ex_get_network_domain(
-            '8cdfd607-f429-4df6-9352-162cfc0891be')
-        rule = self.driver.ex_list_firewall_rules(net)[0]
-        rule.source.address_list_id = None
-        rule.source.any_ip = False
-        rule.source.ip_address = '10.2.1.1'
-        rule.source.ip_prefix_size = '10'
-        rule.destination.address_list_id = None
-        rule.destination.any_ip = False
-        rule.destination.ip_address = '10.0.0.1'
-        rule.destination.ip_prefix_size = '20'
-        self.driver.ex_create_firewall_rule(net, rule, 'LAST')
-
-    def test_ex_create_firewall_rule_address_list(self):
-        net = self.driver.ex_get_network_domain('8cdfd607-f429-4df6-9352-162cfc0891be')
-        rule = self.driver.ex_list_firewall_rules(net)[0]
-        rule.source.address_list_id = '12345'
-        rule.destination.address_list_id = '12345'
-        self.driver.ex_create_firewall_rule(net, rule, 'LAST')
-
-    def test_ex_create_firewall_rule_port_list(self):
-        net = self.driver.ex_get_network_domain('8cdfd607-f429-4df6-9352-162cfc0891be')
-        rule = self.driver.ex_list_firewall_rules(net)[0]
-        rule.source.port_list_id = '12345'
-        rule.destination.port_list_id = '12345'
-        self.driver.ex_create_firewall_rule(net, rule, 'LAST')
-
-    def test_ex_create_firewall_rule_port(self):
-        net = self.driver.ex_get_network_domain(
-            '8cdfd607-f429-4df6-9352-162cfc0891be')
-        rule = self.driver.ex_list_firewall_rules(net)[0]
-        rule.source.port_list_id = None
-        rule.source.port_begin = '8000'
-        rule.source.port_end = '8005'
-        rule.destination.port_list_id = None
-        rule.destination.port_begin = '7000'
-        rule.destination.port_end = '7005'
-        self.driver.ex_create_firewall_rule(net, rule, 'LAST')
-
-    def test_ex_create_firewall_rule_ALL_VALUES(self):
-        net = self.driver.ex_get_network_domain('8cdfd607-f429-4df6-9352-162cfc0891be')
-        rules = self.driver.ex_list_firewall_rules(net)
-        for rule in rules:
-            self.driver.ex_create_firewall_rule(net, rule, 'LAST')
-
-    def test_ex_create_firewall_rule_WITH_POSITION_RULE(self):
-        net = self.driver.ex_get_network_domain('8cdfd607-f429-4df6-9352-162cfc0891be')
-        rules = self.driver.ex_list_firewall_rules(net)
-        rule = self.driver.ex_create_firewall_rule(net, rules[-2], 'BEFORE', rules[-1])
-        self.assertEqual(rule.id, 'd0a20f59-77b9-4f28-a63b-e58496b73a6c')
-
-    def test_ex_create_firewall_rule_WITH_POSITION_RULE_STR(self):
-        net = self.driver.ex_get_network_domain('8cdfd607-f429-4df6-9352-162cfc0891be')
-        rules = self.driver.ex_list_firewall_rules(net)
-        rule = self.driver.ex_create_firewall_rule(net, rules[-2], 'BEFORE', 'RULE_WITH_SOURCE_AND_DEST')
-        self.assertEqual(rule.id, 'd0a20f59-77b9-4f28-a63b-e58496b73a6c')
-
-    def test_ex_create_firewall_rule_FAIL_POSITION(self):
-        net = self.driver.ex_get_network_domain('8cdfd607-f429-4df6-9352-162cfc0891be')
-        rules = self.driver.ex_list_firewall_rules(net)
-        with self.assertRaises(ValueError):
-            self.driver.ex_create_firewall_rule(net, rules[0], 'BEFORE')
-
-    def test_ex_create_firewall_rule_FAIL_POSITION_WITH_RULE(self):
-        net = self.driver.ex_get_network_domain('8cdfd607-f429-4df6-9352-162cfc0891be')
-        rules = self.driver.ex_list_firewall_rules(net)
-        with self.assertRaises(ValueError):
-            self.driver.ex_create_firewall_rule(net, rules[0], 'LAST', 'RULE_WITH_SOURCE_AND_DEST')
-
-    def test_ex_get_firewall_rule(self):
-        net = self.driver.ex_get_network_domain('8cdfd607-f429-4df6-9352-162cfc0891be')
-        rule = self.driver.ex_get_firewall_rule(net, 'd0a20f59-77b9-4f28-a63b-e58496b73a6c')
-        self.assertEqual(rule.id, 'd0a20f59-77b9-4f28-a63b-e58496b73a6c')
-
-    def test_ex_set_firewall_rule_state(self):
-        net = self.driver.ex_get_network_domain('8cdfd607-f429-4df6-9352-162cfc0891be')
-        rule = self.driver.ex_get_firewall_rule(net, 'd0a20f59-77b9-4f28-a63b-e58496b73a6c')
-        result = self.driver.ex_set_firewall_rule_state(rule, False)
-        self.assertTrue(result)
-
-    def test_ex_delete_firewall_rule(self):
-        net = self.driver.ex_get_network_domain('8cdfd607-f429-4df6-9352-162cfc0891be')
-        rule = self.driver.ex_get_firewall_rule(net, 'd0a20f59-77b9-4f28-a63b-e58496b73a6c')
-        result = self.driver.ex_delete_firewall_rule(rule)
-        self.assertTrue(result)
-
-    def test_ex_edit_firewall_rule(self):
-        net = self.driver.ex_get_network_domain(
-            '8cdfd607-f429-4df6-9352-162cfc0891be')
-        rule = self.driver.ex_get_firewall_rule(
-            net, 'd0a20f59-77b9-4f28-a63b-e58496b73a6c')
-        rule.source.any_ip = True
-        result = self.driver.ex_edit_firewall_rule(rule=rule, position='LAST')
-        self.assertTrue(result)
-
-    def test_ex_edit_firewall_rule_source_ipaddresslist(self):
-        net = self.driver.ex_get_network_domain(
-            '8cdfd607-f429-4df6-9352-162cfc0891be')
-        rule = self.driver.ex_get_firewall_rule(
-            net, 'd0a20f59-77b9-4f28-a63b-e58496b73a6c')
-        rule.source.address_list_id = '802abc9f-45a7-4efb-9d5a-810082368222'
-        rule.source.any_ip = False
-        rule.source.ip_address = '10.0.0.1'
-        rule.source.ip_prefix_size = 10
-        result = self.driver.ex_edit_firewall_rule(rule=rule, position='LAST')
-        self.assertTrue(result)
-
-    def test_ex_edit_firewall_rule_destination_ipaddresslist(self):
-        net = self.driver.ex_get_network_domain(
-            '8cdfd607-f429-4df6-9352-162cfc0891be')
-        rule = self.driver.ex_get_firewall_rule(
-            net, 'd0a20f59-77b9-4f28-a63b-e58496b73a6c')
-        rule.destination.address_list_id = '802abc9f-45a7-4efb-9d5a-810082368222'
-        rule.destination.any_ip = False
-        rule.destination.ip_address = '10.0.0.1'
-        rule.destination.ip_prefix_size = 10
-        result = self.driver.ex_edit_firewall_rule(rule=rule, position='LAST')
-        self.assertTrue(result)
-
-    def test_ex_edit_firewall_rule_destination_ipaddress(self):
-        net = self.driver.ex_get_network_domain(
-            '8cdfd607-f429-4df6-9352-162cfc0891be')
-        rule = self.driver.ex_get_firewall_rule(
-            net, 'd0a20f59-77b9-4f28-a63b-e58496b73a6c')
-        rule.source.address_list_id = None
-        rule.source.any_ip = False
-        rule.source.ip_address = '10.0.0.1'
-        rule.source.ip_prefix_size = '10'
-        result = self.driver.ex_edit_firewall_rule(rule=rule, position='LAST')
-        self.assertTrue(result)
-
-    def test_ex_edit_firewall_rule_source_ipaddress(self):
-        net = self.driver.ex_get_network_domain(
-            '8cdfd607-f429-4df6-9352-162cfc0891be')
-        rule = self.driver.ex_get_firewall_rule(
-            net, 'd0a20f59-77b9-4f28-a63b-e58496b73a6c')
-        rule.destination.address_list_id = None
-        rule.destination.any_ip = False
-        rule.destination.ip_address = '10.0.0.1'
-        rule.destination.ip_prefix_size = '10'
-        result = self.driver.ex_edit_firewall_rule(rule=rule, position='LAST')
-        self.assertTrue(result)
-
-    def test_ex_edit_firewall_rule_with_relative_rule(self):
-        net = self.driver.ex_get_network_domain(
-            '8cdfd607-f429-4df6-9352-162cfc0891be')
-        rule = self.driver.ex_get_firewall_rule(
-            net, 'd0a20f59-77b9-4f28-a63b-e58496b73a6c')
-        placement_rule = self.driver.ex_list_firewall_rules(
-            network_domain=net)[-1]
-        result = self.driver.ex_edit_firewall_rule(
-            rule=rule, position='BEFORE',
-            relative_rule_for_position=placement_rule)
-        self.assertTrue(result)
-
-    def test_ex_edit_firewall_rule_with_relative_rule_by_name(self):
-        net = self.driver.ex_get_network_domain(
-            '8cdfd607-f429-4df6-9352-162cfc0891be')
-        rule = self.driver.ex_get_firewall_rule(
-            net, 'd0a20f59-77b9-4f28-a63b-e58496b73a6c')
-        placement_rule = self.driver.ex_list_firewall_rules(
-            network_domain=net)[-1]
-        result = self.driver.ex_edit_firewall_rule(
-            rule=rule, position='BEFORE',
-            relative_rule_for_position=placement_rule.name)
-        self.assertTrue(result)
-
-    def test_ex_edit_firewall_rule_source_portlist(self):
-        net = self.driver.ex_get_network_domain(
-            '8cdfd607-f429-4df6-9352-162cfc0891be')
-        rule = self.driver.ex_get_firewall_rule(
-            net, 'd0a20f59-77b9-4f28-a63b-e58496b73a6c')
-        rule.source.port_list_id = '802abc9f-45a7-4efb-9d5a-810082368222'
-        result = self.driver.ex_edit_firewall_rule(rule=rule, position='LAST')
-        self.assertTrue(result)
-
-    def test_ex_edit_firewall_rule_source_port(self):
-        net = self.driver.ex_get_network_domain(
-            '8cdfd607-f429-4df6-9352-162cfc0891be')
-        rule = self.driver.ex_get_firewall_rule(
-            net, 'd0a20f59-77b9-4f28-a63b-e58496b73a6c')
-        rule.source.port_list_id = None
-        rule.source.port_begin = '3'
-        rule.source.port_end = '10'
-        result = self.driver.ex_edit_firewall_rule(rule=rule, position='LAST')
-        self.assertTrue(result)
-
-    def test_ex_edit_firewall_rule_destination_portlist(self):
-        net = self.driver.ex_get_network_domain(
-            '8cdfd607-f429-4df6-9352-162cfc0891be')
-        rule = self.driver.ex_get_firewall_rule(
-            net, 'd0a20f59-77b9-4f28-a63b-e58496b73a6c')
-        rule.destination.port_list_id = '802abc9f-45a7-4efb-9d5a-810082368222'
-        result = self.driver.ex_edit_firewall_rule(rule=rule, position='LAST')
-        self.assertTrue(result)
-
-    def test_ex_edit_firewall_rule_destination_port(self):
-        net = self.driver.ex_get_network_domain(
-            '8cdfd607-f429-4df6-9352-162cfc0891be')
-        rule = self.driver.ex_get_firewall_rule(
-            net, 'd0a20f59-77b9-4f28-a63b-e58496b73a6c')
-        rule.destination.port_list_id = None
-        rule.destination.port_begin = '3'
-        rule.destination.port_end = '10'
-        result = self.driver.ex_edit_firewall_rule(rule=rule, position='LAST')
-        self.assertTrue(result)
-
-    def test_ex_edit_firewall_rule_invalid_position_fail(self):
-        net = self.driver.ex_get_network_domain(
-            '8cdfd607-f429-4df6-9352-162cfc0891be')
-        rule = self.driver.ex_get_firewall_rule(
-            net, 'd0a20f59-77b9-4f28-a63b-e58496b73a6c')
-        with self.assertRaises(ValueError):
-            self.driver.ex_edit_firewall_rule(rule=rule, position='BEFORE')
-
-    def test_ex_edit_firewall_rule_invalid_position_relative_rule_fail(self):
-        net = self.driver.ex_get_network_domain(
-            '8cdfd607-f429-4df6-9352-162cfc0891be')
-        rule = self.driver.ex_get_firewall_rule(
-            net, 'd0a20f59-77b9-4f28-a63b-e58496b73a6c')
-        relative_rule = self.driver.ex_list_firewall_rules(
-            network_domain=net)[-1]
-        with self.assertRaises(ValueError):
-            self.driver.ex_edit_firewall_rule(rule=rule, position='FIRST',
-                                              relative_rule_for_position=relative_rule)
-
-    def test_ex_create_nat_rule(self):
-        net = self.driver.ex_get_network_domain('8cdfd607-f429-4df6-9352-162cfc0891be')
-        rule = self.driver.ex_create_nat_rule(net, '1.2.3.4', '4.3.2.1')
-        self.assertEqual(rule.id, 'd31c2db0-be6b-4d50-8744-9a7a534b5fba')
-
-    def test_ex_list_nat_rules(self):
-        net = self.driver.ex_get_network_domain('8cdfd607-f429-4df6-9352-162cfc0891be')
-        rules = self.driver.ex_list_nat_rules(net)
-        self.assertEqual(rules[0].id, '2187a636-7ebb-49a1-a2ff-5d617f496dce')
-        self.assertEqual(rules[0].internal_ip, '10.0.0.15')
-        self.assertEqual(rules[0].external_ip, '165.180.12.18')
-
-    def test_ex_get_nat_rule(self):
-        net = self.driver.ex_get_network_domain('8cdfd607-f429-4df6-9352-162cfc0891be')
-        rule = self.driver.ex_get_nat_rule(net, '2187a636-7ebb-49a1-a2ff-5d617f496dce')
-        self.assertEqual(rule.id, '2187a636-7ebb-49a1-a2ff-5d617f496dce')
-        self.assertEqual(rule.internal_ip, '10.0.0.16')
-        self.assertEqual(rule.external_ip, '165.180.12.19')
-
-    def test_ex_delete_nat_rule(self):
-        net = self.driver.ex_get_network_domain('8cdfd607-f429-4df6-9352-162cfc0891be')
-        rule = self.driver.ex_get_nat_rule(net, '2187a636-7ebb-49a1-a2ff-5d617f496dce')
-        result = self.driver.ex_delete_nat_rule(rule)
-        self.assertTrue(result)
-
-    def test_ex_enable_monitoring(self):
-        node = self.driver.list_nodes()[0]
-        result = self.driver.ex_enable_monitoring(node, "ADVANCED")
-        self.assertTrue(result)
-
-    def test_ex_disable_monitoring(self):
-        node = self.driver.list_nodes()[0]
-        result = self.driver.ex_disable_monitoring(node)
-        self.assertTrue(result)
-
-    def test_ex_change_monitoring_plan(self):
-        node = self.driver.list_nodes()[0]
-        result = self.driver.ex_update_monitoring_plan(node, "ESSENTIALS")
-        self.assertTrue(result)
-
-    def test_ex_add_storage_to_node(self):
-        node = self.driver.list_nodes()[0]
-        result = self.driver.ex_add_storage_to_node(node, 30, 'PERFORMANCE')
-        self.assertTrue(result)
-
-    def test_ex_remove_storage_from_node(self):
-        node = self.driver.list_nodes()[0]
-        result = self.driver.ex_remove_storage_from_node(node, 0)
-        self.assertTrue(result)
-
-    def test_ex_change_storage_speed(self):
-        node = self.driver.list_nodes()[0]
-        result = self.driver.ex_change_storage_speed(node, 1, 'PERFORMANCE')
-        self.assertTrue(result)
-
-    def test_ex_change_storage_size(self):
-        node = self.driver.list_nodes()[0]
-        result = self.driver.ex_change_storage_size(node, 1, 100)
-        self.assertTrue(result)
-
-    def test_ex_clone_node_to_image(self):
-        node = self.driver.list_nodes()[0]
-        result = self.driver.ex_clone_node_to_image(node, 'my image', 'a description')
-        self.assertTrue(result)
-
-    def test_ex_update_node(self):
-        node = self.driver.list_nodes()[0]
-        result = self.driver.ex_update_node(node, 'my new name', 'a description', 2, 4048)
-        self.assertTrue(result)
-
-    def test_ex_reconfigure_node(self):
-        node = self.driver.list_nodes()[0]
-        result = self.driver.ex_reconfigure_node(node, 4, 4, 1, 'HIGHPERFORMANCE')
-        self.assertTrue(result)
-
-    def test_ex_get_location_by_id(self):
-        location = self.driver.ex_get_location_by_id('NA9')
-        self.assertTrue(location.id, 'NA9')
-
-    def test_ex_get_location_by_id_NO_LOCATION(self):
-        location = self.driver.ex_get_location_by_id(None)
-        self.assertIsNone(location)
-
-    def test_ex_get_base_image_by_id(self):
-        image_id = self.driver.list_images()[0].id
-        image = self.driver.ex_get_base_image_by_id(image_id)
-        self.assertEqual(image.extra['OS_type'], 'UNIX')
-
-    def test_ex_get_customer_image_by_id(self):
-        image_id = self.driver.ex_list_customer_images()[1].id
-        image = self.driver.ex_get_customer_image_by_id(image_id)
-        self.assertEqual(image.extra['OS_type'], 'WINDOWS')
-
-    def test_ex_get_image_by_id_base_img(self):
-        image_id = self.driver.list_images()[1].id
-        image = self.driver.ex_get_base_image_by_id(image_id)
-        self.assertEqual(image.extra['OS_type'], 'WINDOWS')
-
-    def test_ex_get_image_by_id_customer_img(self):
-        image_id = self.driver.ex_list_customer_images()[0].id
-        image = self.driver.ex_get_customer_image_by_id(image_id)
-        self.assertEqual(image.extra['OS_type'], 'UNIX')
-
-    def test_ex_get_image_by_id_customer_FAIL(self):
-        image_id = 'FAKE_IMAGE_ID'
-        with self.assertRaises(DimensionDataAPIException):
-            self.driver.ex_get_base_image_by_id(image_id)
-
-    def test_ex_create_anti_affinity_rule(self):
-        node_list = self.driver.list_nodes()
-        success = self.driver.ex_create_anti_affinity_rule([node_list[0], node_list[1]])
-        self.assertTrue(success)
-
-    def test_ex_create_anti_affinity_rule_TUPLE(self):
-        node_list = self.driver.list_nodes()
-        success = self.driver.ex_create_anti_affinity_rule((node_list[0], node_list[1]))
-        self.assertTrue(success)
-
-    def test_ex_create_anti_affinity_rule_TUPLE_STR(self):
-        node_list = self.driver.list_nodes()
-        success = self.driver.ex_create_anti_affinity_rule((node_list[0].id, node_list[1].id))
-        self.assertTrue(success)
-
-    def test_ex_create_anti_affinity_rule_FAIL_STR(self):
-        node_list = 'string'
-        with self.assertRaises(TypeError):
-            self.driver.ex_create_anti_affinity_rule(node_list)
-
-    def test_ex_create_anti_affinity_rule_FAIL_EXISTING(self):
-        node_list = self.driver.list_nodes()
-        DimensionDataMockHttp.type = 'FAIL_EXISTING'
-        with self.assertRaises(DimensionDataAPIException):
-            self.driver.ex_create_anti_affinity_rule((node_list[0], node_list[1]))
-
-    def test_ex_delete_anti_affinity_rule(self):
-        net_domain = self.driver.ex_list_network_domains()[0]
-        rule = self.driver.ex_list_anti_affinity_rules(network_domain=net_domain)[0]
-        success = self.driver.ex_delete_anti_affinity_rule(rule)
-        self.assertTrue(success)
-
-    def test_ex_delete_anti_affinity_rule_STR(self):
-        net_domain = self.driver.ex_list_network_domains()[0]
-        rule = self.driver.ex_list_anti_affinity_rules(network_domain=net_domain)[0]
-        success = self.driver.ex_delete_anti_affinity_rule(rule.id)
-        self.assertTrue(success)
-
-    def test_ex_delete_anti_affinity_rule_FAIL(self):
-        net_domain = self.driver.ex_list_network_domains()[0]
-        rule = self.driver.ex_list_anti_affinity_rules(network_domain=net_domain)[0]
-        DimensionDataMockHttp.type = 'FAIL'
-        with self.assertRaises(DimensionDataAPIException):
-            self.driver.ex_delete_anti_affinity_rule(rule)
-
-    def test_ex_list_anti_affinity_rules_NETWORK_DOMAIN(self):
-        net_domain = self.driver.ex_list_network_domains()[0]
-        rules = self.driver.ex_list_anti_affinity_rules(network_domain=net_domain)
-        self.assertTrue(isinstance(rules, list))
-        self.assertEqual(len(rules), 2)
-        self.assertTrue(isinstance(rules[0].id, str))
-        self.assertTrue(isinstance(rules[0].node_list, list))
-
-    def test_ex_list_anti_affinity_rules_NETWORK(self):
-        network = self.driver.list_networks()[0]
-        rules = self.driver.ex_list_anti_affinity_rules(network=network)
-        self.assertTrue(isinstance(rules, list))
-        self.assertEqual(len(rules), 2)
-        self.assertTrue(isinstance(rules[0].id, str))
-        self.assertTrue(isinstance(rules[0].node_list, list))
-
-    def test_ex_list_anti_affinity_rules_NODE(self):
-        node = self.driver.list_nodes()[0]
-        rules = self.driver.ex_list_anti_affinity_rules(node=node)
-        self.assertTrue(isinstance(rules, list))
-        self.assertEqual(len(rules), 2)
-        self.assertTrue(isinstance(rules[0].id, str))
-        self.assertTrue(isinstance(rules[0].node_list, list))
-
-    def test_ex_list_anti_affinity_rules_PAGINATED(self):
-        net_domain = self.driver.ex_list_network_domains()[0]
-        DimensionDataMockHttp.type = 'PAGINATED'
-        rules = self.driver.ex_list_anti_affinity_rules(network_domain=net_domain)
-        self.assertTrue(isinstance(rules, list))
-        self.assertEqual(len(rules), 4)
-        self.assertTrue(isinstance(rules[0].id, str))
-        self.assertTrue(isinstance(rules[0].node_list, list))
-
-    def test_ex_list_anti_affinity_rules_ALLFILTERS(self):
-        net_domain = self.driver.ex_list_network_domains()[0]
-        DimensionDataMockHttp.type = 'ALLFILTERS'
-        rules = self.driver.ex_list_anti_affinity_rules(network_domain=net_domain, filter_id='FAKE_ID', filter_state='FAKE_STATE')
-        self.assertTrue(isinstance(rules, list))
-        self.assertEqual(len(rules), 2)
-        self.assertTrue(isinstance(rules[0].id, str))
-        self.assertTrue(isinstance(rules[0].node_list, list))
-
-    def test_ex_list_anti_affinity_rules_BAD_ARGS(self):
-        with self.assertRaises(ValueError):
-            self.driver.ex_list_anti_affinity_rules(network='fake_network', network_domain='fake_network_domain')
-
-    def test_ex_create_tag_key(self):
-        success = self.driver.ex_create_tag_key('MyTestKey')
-        self.assertTrue(success)
-
-    def test_ex_create_tag_key_ALLPARAMS(self):
-        self.driver.connection._get_orgId()
-        DimensionDataMockHttp.type = 'ALLPARAMS'
-        success = self.driver.ex_create_tag_key('MyTestKey', description="Test Key Desc.", value_required=False, display_on_report=False)
-        self.assertTrue(success)
-
-    def test_ex_create_tag_key_BADREQUEST(self):
-        self.driver.connection._get_orgId()
-        DimensionDataMockHttp.type = 'BADREQUEST'
-        with self.assertRaises(DimensionDataAPIException):
-            self.driver.ex_create_tag_key('MyTestKey')
-
-    def test_ex_list_tag_keys(self):
-        tag_keys = self.driver.ex_list_tag_keys()
-        self.assertTrue(isinstance(tag_keys, list))
-        self.assertTrue(isinstance(tag_keys[0], DimensionDataTagKey))
-        self.assertTrue(isinstance(tag_keys[0].id, str))
-
-    def test_ex_list_tag_keys_ALLFILTERS(self):
-        self.driver.connection._get_orgId()
-        DimensionDataMockHttp.type = 'ALLFILTERS'
-        self.driver.ex_list_tag_keys(id='fake_id', name='fake_name', value_required=False, display_on_report=False)
-
-    def test_ex_get_tag_by_id(self):
-        tag = self.driver.ex_get_tag_key_by_id('d047c609-93d7-4bc5-8fc9-732c85840075')
-        self.assertTrue(isinstance(tag, DimensionDataTagKey))
-
-    def test_ex_get_tag_by_id_NOEXIST(self):
-        self.driver.connection._get_orgId()
-        DimensionDataMockHttp.type = 'NOEXIST'
-        with self.assertRaises(DimensionDataAPIException):
-            self.driver.ex_get_tag_key_by_id('d047c609-93d7-4bc5-8fc9-732c85840075')
-
-    def test_ex_get_tag_by_name(self):
-        self.driver.connection._get_orgId()
-        DimensionDataMockHttp.type = 'SINGLE'
-        tag = self.driver.ex_get_tag_key_by_name('LibcloudTest')
-        self.assertTrue(isinstance(tag, DimensionDataTagKey))
-
-    def test_ex_get_tag_by_name_NOEXIST(self):
-        with self.assertRaises(ValueError):
-            self.driver.ex_get_tag_key_by_name('LibcloudTest')
-
-    def test_ex_modify_tag_key_NAME(self):
-        tag_key = self.driver.ex_list_tag_keys()[0]
-        DimensionDataMockHttp.type = 'NAME'
-        success = self.driver.ex_modify_tag_key(tag_key, name='NewName')
-        self.assertTrue(success)
-
-    def test_ex_modify_tag_key_NOTNAME(self):
-        tag_key = self.driver.ex_list_tag_keys()[0]
-        DimensionDataMockHttp.type = 'NOTNAME'
-        success = self.driver.ex_modify_tag_key(tag_key, description='NewDesc', value_required=False, display_on_report=True)
-        self.assertTrue(success)
-
-    def test_ex_modify_tag_key_NOCHANGE(self):
-        tag_key = self.driver.ex_list_tag_keys()[0]
-        DimensionDataMockHttp.type = 'NOCHANGE'
-        with self.assertRaises(DimensionDataAPIException):
-            self.driver.ex_modify_tag_key(tag_key)
-
-    def test_ex_remove_tag_key(self):
-        tag_key = self.driver.ex_list_tag_keys()[0]
-        success = self.driver.ex_remove_tag_key(tag_key)
-        self.assertTrue(success)
-
-    def test_ex_remove_tag_key_NOEXIST(self):
-        tag_key = self.driver.ex_list_tag_keys()[0]
-        DimensionDataMockHttp.type = 'NOEXIST'
-        with self.assertRaises(DimensionDataAPIException):
-            self.driver.ex_remove_tag_key(tag_key)
-
-    def test_ex_apply_tag_to_asset(self):
-        node = self.driver.list_nodes()[0]
-        success = self.driver.ex_apply_tag_to_asset(node, 'TagKeyName', 'FakeValue')
-        self.assertTrue(success)
-
-    def test_ex_apply_tag_to_asset_NOVALUE(self):
-        node = self.driver.list_nodes()[0]
-        DimensionDataMockHttp.type = 'NOVALUE'
-        success = self.driver.ex_apply_tag_to_asset(node, 'TagKeyName')
-        self.assertTrue(success)
-
-    def test_ex_apply_tag_to_asset_NOTAGKEY(self):
-        node = self.driver.list_nodes()[0]
-        DimensionDataMockHttp.type = 'NOTAGKEY'
-        with self.assertRaises(DimensionDataAPIException):
-            self.driver.ex_apply_tag_to_asset(node, 'TagKeyNam')
-
-    def test_ex_apply_tag_to_asset_BADASSETTYPE(self):
-        network = self.driver.list_networks()[0]
-        DimensionDataMockHttp.type = 'NOTAGKEY'
-        with self.assertRaises(TypeError):
-            self.driver.ex_apply_tag_to_asset(network, 'TagKeyNam')
-
-    def test_ex_remove_tag_from_asset(self):
-        node = self.driver.list_nodes()[0]
-        success = self.driver.ex_remove_tag_from_asset(node, 'TagKeyName')
-        self.assertTrue(success)
-
-    def test_ex_remove_tag_from_asset_NOTAG(self):
-        node = self.driver.list_nodes()[0]
-        DimensionDataMockHttp.type = 'NOTAG'
-        with self.assertRaises(DimensionDataAPIException):
-            self.driver.ex_remove_tag_from_asset(node, 'TagKeyNam')
-
-    def test_ex_list_tags(self):
-        tags = self.driver.ex_list_tags()
-        self.assertTrue(isinstance(tags, list))
-        self.assertTrue(isinstance(tags[0], DimensionDataTag))
-        self.assertTrue(len(tags) == 3)
-
-    def test_ex_list_tags_ALLPARAMS(self):
-        self.driver.connection._get_orgId()
-        DimensionDataMockHttp.type = 'ALLPARAMS'
-        tags = self.driver.ex_list_tags(asset_id='fake_asset_id', asset_type='fake_asset_type',
-                                        location='fake_location', tag_key_name='fake_tag_key_name',
-                                        tag_key_id='fake_tag_key_id', value='fake_value',
-                                        value_required=False, display_on_report=False)
-        self.assertTrue(isinstance(tags, list))
-        self.assertTrue(isinstance(tags[0], DimensionDataTag))
-        self.assertTrue(len(tags) == 3)
-
-    def test_priv_location_to_location_id(self):
-        location = self.driver.ex_get_location_by_id('NA9')
-        self.assertEqual(
-            self.driver._location_to_location_id(location),
-            'NA9'
-        )
-
-    def test_priv_location_to_location_id_STR(self):
-        self.assertEqual(
-            self.driver._location_to_location_id('NA9'),
-            'NA9'
-        )
-
-    def test_priv_location_to_location_id_TYPEERROR(self):
-        with self.assertRaises(TypeError):
-            self.driver._location_to_location_id([1, 2, 3])
-
-    def test_priv_image_needs_auth_os_img(self):
-        image = self.driver.list_images()[1]
-        self.assertTrue(self.driver._image_needs_auth(image))
-
-    def test_priv_image_needs_auth_os_img_STR(self):
-        image = self.driver.list_images()[1].id
-        self.assertTrue(self.driver._image_needs_auth(image))
-
-    def test_priv_image_needs_auth_cust_img_windows(self):
-        image = self.driver.ex_list_customer_images()[1]
-        self.assertTrue(self.driver._image_needs_auth(image))
-
-    def test_priv_image_needs_auth_cust_img_windows_STR(self):
-        image = self.driver.ex_list_customer_images()[1].id
-        self.assertTrue(self.driver._image_needs_auth(image))
-
-    def test_priv_image_needs_auth_cust_img_linux(self):
-        image = self.driver.ex_list_customer_images()[0]
-        self.assertTrue(not self.driver._image_needs_auth(image))
-
-    def test_priv_image_needs_auth_cust_img_linux_STR(self):
-        image = self.driver.ex_list_customer_images()[0].id
-        self.assertTrue(not self.driver._image_needs_auth(image))
-
-    def test_summary_usage_report(self):
-        report = self.driver.ex_summary_usage_report('2016-06-01', '2016-06-30')
-        report_content = report
-        self.assertEqual(len(report_content), 13)
-        self.assertEqual(len(report_content[0]), 6)
-
-    def test_detailed_usage_report(self):
-        report = self.driver.ex_detailed_usage_report('2016-06-01', '2016-06-30')
-        report_content = report
-        self.assertEqual(len(report_content), 42)
-        self.assertEqual(len(report_content[0]), 4)
-
-    def test_audit_log_report(self):
-        report = self.driver.ex_audit_log_report('2016-06-01', '2016-06-30')
-        report_content = report
-        self.assertEqual(len(report_content), 25)
-        self.assertEqual(report_content[2][2], 'OEC_SYSTEM')
-
-    def test_ex_list_ip_address_list(self):
-        net_domain = self.driver.ex_list_network_domains()[0]
-        ip_list = self.driver.ex_list_ip_address_list(
-            ex_network_domain=net_domain)
-        self.assertTrue(isinstance(ip_list, list))
-        self.assertEqual(len(ip_list), 4)
-        self.assertTrue(isinstance(ip_list[0].name, str))
-        self.assertTrue(isinstance(ip_list[0].description, str))
-        self.assertTrue(isinstance(ip_list[0].ip_version, str))
-        self.assertTrue(isinstance(ip_list[0].state, str))
-        self.assertTrue(isinstance(ip_list[0].create_time, str))
-        self.assertTrue(isinstance(ip_list[0].child_ip_address_lists, list))
-        self.assertEqual(len(ip_list[1].child_ip_address_lists), 1)
-        self.assertTrue(isinstance(ip_list[1].child_ip_address_lists[0].name,
-                                   str))
-
-    def test_ex_get_ip_address_list(self):
-        net_domain = self.driver.ex_list_network_domains()[0]
-        DimensionDataMockHttp.type = 'FILTERBYNAME'
-        ip_list = self.driver.ex_get_ip_address_list(
-            ex_network_domain=net_domain.id,
-            ex_ip_address_list_name='Test_IP_Address_List_3')
-        self.assertTrue(isinstance(ip_list, list))
-        self.assertEqual(len(ip_list), 1)
-        self.assertTrue(isinstance(ip_list[0].name, str))
-        self.assertTrue(isinstance(ip_list[0].description, str))
-        self.assertTrue(isinstance(ip_list[0].ip_version, str))
-        self.assertTrue(isinstance(ip_list[0].state, str))
-        self.assertTrue(isinstance(ip_list[0].create_time, str))
-        ips = ip_list[0].ip_address_collection
-        self.assertEqual(len(ips), 3)
-        self.assertTrue(isinstance(ips[0].begin, str))
-        self.assertTrue(isinstance(ips[0].prefix_size, str))
-        self.assertTrue(isinstance(ips[2].end, str))
-
-    def test_ex_create_ip_address_list_FAIL(self):
-        net_domain = self.driver.ex_list_network_domains()[0]
-
-        with self.assertRaises(TypeError):
-            self.driver.ex_create_ip_address_list(
-                ex_network_domain=net_domain.id)
-
-    def test_ex_create_ip_address_list(self):
-        name = "Test_IP_Address_List_3"
-        description = "Test Description"
-        ip_version = "IPV4"
-        child_ip_address_list_id = '0291ef78-4059-4bc1-b433-3f6ad698dc41'
-        child_ip_address_list = DimensionDataChildIpAddressList(
-            id=child_ip_address_list_id,
-            name="test_child_ip_addr_list")
-        net_domain = self.driver.ex_list_network_domains()[0]
-        ip_address_1 = DimensionDataIpAddress(begin='190.2.2.100')
-        ip_address_2 = DimensionDataIpAddress(begin='190.2.2.106',
-                                              end='190.2.2.108')
-        ip_address_3 = DimensionDataIpAddress(begin='190.2.2.0',
-                                              prefix_size='24')
-        ip_address_collection = [ip_address_1, ip_address_2,
-                                 ip_address_3]
-
-        # Create IP Address List
-        success = self.driver.ex_create_ip_address_list(
-            ex_network_domain=net_domain, name=name,
-            ip_version=ip_version, description=description,
-            ip_address_collection=ip_address_collection,
-            child_ip_address_list=child_ip_address_list)
-
-        self.assertTrue(success)
-
-    def test_ex_create_ip_address_list_STR(self):
-        name = "Test_IP_Address_List_3"
-        description = "Test Description"
-        ip_version = "IPV4"
-        child_ip_address_list_id = '0291ef78-4059-4bc1-b433-3f6ad698dc41'
-        net_domain = self.driver.ex_list_network_domains()[0]
-        ip_address_1 = DimensionDataIpAddress(begin='190.2.2.100')
-        ip_address_2 = DimensionDataIpAddress(begin='190.2.2.106',
-                                              end='190.2.2.108')
-        ip_address_3 = DimensionDataIpAddress(begin='190.2.2.0',
-                                              prefix_size='24')
-        ip_address_collection = [ip_address_1, ip_address_2,
-                                 ip_address_3]
-
-        # Create IP Address List
-        success = self.driver.ex_create_ip_address_list(
-            ex_network_domain=net_domain.id, name=name,
-            ip_version=ip_version, description=description,
-            ip_address_collection=ip_address_collection,
-            child_ip_address_list=child_ip_address_list_id)
-
-        self.assertTrue(success)
-
-    def test_ex_edit_ip_address_list(self):
-        ip_address_1 = DimensionDataIpAddress(begin='190.2.2.111')
-        ip_address_collection = [ip_address_1]
-
-        child_ip_address_list = DimensionDataChildIpAddressList(
-            id='2221ef78-4059-4bc1-b433-3f6ad698dc41',
-            name="test_child_ip_address_list edited")
-
-        ip_address_list = DimensionDataIpAddressList(
-            id='1111ef78-4059-4bc1-b433-3f6ad698d111',
-            name="test ip address list edited",
-            ip_version="IPv4", description="test",
-            ip_address_collection=ip_address_collection,
-            child_ip_address_lists=child_ip_address_list,
-            state="NORMAL",
-            create_time='2015-09-29T02:49:45'
-        )
-
-        success = self.driver.ex_edit_ip_address_list(
-            ex_ip_address_list=ip_address_list,
-            description="test ip address list",
-            ip_address_collection=ip_address_collection,
-            child_ip_address_lists=child_ip_address_list
-        )
-
-        self.assertTrue(success)
-
-    def test_ex_edit_ip_address_list_STR(self):
-        ip_address_1 = DimensionDataIpAddress(begin='190.2.2.111')
-        ip_address_collection = [ip_address_1]
-
-        child_ip_address_list = DimensionDataChildIpAddressList(
-            id='2221ef78-4059-4bc1-b433-3f6ad698dc41',
-            name="test_child_ip_address_list edited")
-
-        success = self.driver.ex_edit_ip_address_list(
-            ex_ip_address_list='84e34850-595d- 436e-a885-7cd37edb24a4',
-            description="test ip address list",
-            ip_address_collection=ip_address_collection,
-            child_ip_address_lists=child_ip_address_list
-        )
-
-        self.assertTrue(success)
-
-    def test_ex_delete_ip_address_list(self):
-        child_ip_address_list = DimensionDataChildIpAddressList(
-            id='2221ef78-4059-4bc1-b433-3f6ad698dc41',
-            name="test_child_ip_address_list edited")
-
-        ip_address_list = DimensionDataIpAddressList(
-            id='1111ef78-4059-4bc1-b433-3f6ad698d111',
-            name="test ip address list edited",
-            ip_versi

<TRUNCATED>

[38/40] libcloud git commit: Remove print for debug

Posted by an...@apache.org.
Remove print for debug


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

Branch: refs/heads/trunk
Commit: 5a1eeae573d689d7bcf727f86b3659fc2071d73d
Parents: 8db131a
Author: Samuel Chong <sa...@gmail.com>
Authored: Fri Dec 2 13:51:38 2016 +1100
Committer: Samuel Chong <sa...@gmail.com>
Committed: Fri Dec 2 13:51:38 2016 +1100

----------------------------------------------------------------------
 libcloud/common/dimensiondata.py          | 2 +-
 libcloud/compute/drivers/dimensiondata.py | 1 -
 2 files changed, 1 insertion(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/libcloud/blob/5a1eeae5/libcloud/common/dimensiondata.py
----------------------------------------------------------------------
diff --git a/libcloud/common/dimensiondata.py b/libcloud/common/dimensiondata.py
index 786a163..bcfd576 100644
--- a/libcloud/common/dimensiondata.py
+++ b/libcloud/common/dimensiondata.py
@@ -483,7 +483,7 @@ class DimensionDataConnection(ConnectionUserAndKey):
     def request_with_orgId_api_2(self, action, params=None, data='',
                                  headers=None, method='GET'):
         action = "%s/%s" % (self.get_resource_path_api_2(), action)
-        print(action)
+
         return super(DimensionDataConnection, self).request(
             action=action,
             params=params, data=data,

http://git-wip-us.apache.org/repos/asf/libcloud/blob/5a1eeae5/libcloud/compute/drivers/dimensiondata.py
----------------------------------------------------------------------
diff --git a/libcloud/compute/drivers/dimensiondata.py b/libcloud/compute/drivers/dimensiondata.py
index b0f248a..bf532f9 100644
--- a/libcloud/compute/drivers/dimensiondata.py
+++ b/libcloud/compute/drivers/dimensiondata.py
@@ -954,7 +954,6 @@ class DimensionDataNodeDriver(NodeDriver):
 
             if len(tagkey_name_value_dictionaries) > 0:
                 for k, v in tagkey_name_value_dictionaries.items():
-                    print(k, v)
                     tag_elem = ET.SubElement(
                         import_image_elem,
                         'urn:tag')


[14/40] libcloud git commit: Unit tests for 2.3

Posted by an...@apache.org.
http://git-wip-us.apache.org/repos/asf/libcloud/blob/bb1b8104/libcloud/test/loadbalancer/test_dimensiondata.py
----------------------------------------------------------------------
diff --git a/libcloud/test/loadbalancer/test_dimensiondata.py b/libcloud/test/loadbalancer/test_dimensiondata.py
deleted file mode 100644
index 2792d83..0000000
--- a/libcloud/test/loadbalancer/test_dimensiondata.py
+++ /dev/null
@@ -1,619 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License.  You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-import sys
-from libcloud.utils.py3 import httplib
-
-from libcloud.common.types import InvalidCredsError
-from libcloud.common.dimensiondata import DimensionDataVIPNode, DimensionDataPool
-from libcloud.common.dimensiondata import DimensionDataPoolMember
-from libcloud.loadbalancer.base import LoadBalancer, Member, Algorithm
-from libcloud.loadbalancer.drivers.dimensiondata \
-    import DimensionDataLBDriver as DimensionData
-from libcloud.loadbalancer.types import State
-
-from libcloud.test import MockHttp, unittest
-from libcloud.test.file_fixtures import LoadBalancerFileFixtures
-
-from libcloud.test.secrets import DIMENSIONDATA_PARAMS
-
-
-class DimensionDataTests(unittest.TestCase):
-
-    def setUp(self):
-        DimensionData.connectionCls.conn_classes = (None, DimensionDataMockHttp)
-        DimensionDataMockHttp.type = None
-        self.driver = DimensionData(*DIMENSIONDATA_PARAMS)
-
-    def test_invalid_region(self):
-        with self.assertRaises(ValueError):
-            self.driver = DimensionData(*DIMENSIONDATA_PARAMS, region='blah')
-
-    def test_invalid_creds(self):
-        DimensionDataMockHttp.type = 'UNAUTHORIZED'
-        with self.assertRaises(InvalidCredsError):
-            self.driver.list_balancers()
-
-    def test_create_balancer(self):
-        self.driver.ex_set_current_network_domain('1234')
-        members = []
-        members.append(Member(
-            id=None,
-            ip='1.2.3.4',
-            port=80))
-
-        balancer = self.driver.create_balancer(
-            name='test',
-            port=80,
-            protocol='http',
-            algorithm=Algorithm.ROUND_ROBIN,
-            members=members,
-            ex_listener_ip_address='5.6.7.8')
-        self.assertEqual(balancer.name, 'test')
-        self.assertEqual(balancer.id, '8334f461-0df0-42d5-97eb-f4678eb26bea')
-        self.assertEqual(balancer.ip, '165.180.12.22')
-        self.assertEqual(balancer.port, 80)
-        self.assertEqual(balancer.extra['pool_id'], '9e6b496d-5261-4542-91aa-b50c7f569c54')
-        self.assertEqual(balancer.extra['network_domain_id'], '1234')
-        self.assertEqual(balancer.extra['listener_ip_address'], '5.6.7.8')
-
-    def test_create_balancer_with_defaults(self):
-        self.driver.ex_set_current_network_domain('1234')
-
-        balancer = self.driver.create_balancer(
-            name='test',
-            port=None,
-            protocol=None,
-            algorithm=None,
-            members=None)
-        self.assertEqual(balancer.name, 'test')
-        self.assertEqual(balancer.id, '8334f461-0df0-42d5-97eb-f4678eb26bea')
-        self.assertEqual(balancer.ip, '165.180.12.22')
-        self.assertEqual(balancer.port, None)
-        self.assertEqual(balancer.extra['pool_id'], '9e6b496d-5261-4542-91aa-b50c7f569c54')
-        self.assertEqual(balancer.extra['network_domain_id'], '1234')
-
-    def test_create_balancer_no_members(self):
-        self.driver.ex_set_current_network_domain('1234')
-        members = None
-
-        balancer = self.driver.create_balancer(
-            name='test',
-            port=80,
-            protocol='http',
-            algorithm=Algorithm.ROUND_ROBIN,
-            members=members)
-        self.assertEqual(balancer.name, 'test')
-        self.assertEqual(balancer.id, '8334f461-0df0-42d5-97eb-f4678eb26bea')
-        self.assertEqual(balancer.ip, '165.180.12.22')
-        self.assertEqual(balancer.port, 80)
-        self.assertEqual(balancer.extra['pool_id'], '9e6b496d-5261-4542-91aa-b50c7f569c54')
-        self.assertEqual(balancer.extra['network_domain_id'], '1234')
-
-    def test_create_balancer_empty_members(self):
-        self.driver.ex_set_current_network_domain('1234')
-        members = []
-
-        balancer = self.driver.create_balancer(
-            name='test',
-            port=80,
-            protocol='http',
-            algorithm=Algorithm.ROUND_ROBIN,
-            members=members)
-        self.assertEqual(balancer.name, 'test')
-        self.assertEqual(balancer.id, '8334f461-0df0-42d5-97eb-f4678eb26bea')
-        self.assertEqual(balancer.ip, '165.180.12.22')
-        self.assertEqual(balancer.port, 80)
-        self.assertEqual(balancer.extra['pool_id'], '9e6b496d-5261-4542-91aa-b50c7f569c54')
-        self.assertEqual(balancer.extra['network_domain_id'], '1234')
-
-    def test_list_balancers(self):
-        bal = self.driver.list_balancers()
-        self.assertEqual(bal[0].name, 'myProduction.Virtual.Listener')
-        self.assertEqual(bal[0].id, '6115469d-a8bb-445b-bb23-d23b5283f2b9')
-        self.assertEqual(bal[0].port, '8899')
-        self.assertEqual(bal[0].ip, '165.180.12.22')
-        self.assertEqual(bal[0].state, State.RUNNING)
-
-    def test_balancer_list_members(self):
-        extra = {'pool_id': '4d360b1f-bc2c-4ab7-9884-1f03ba2768f7',
-                 'network_domain_id': '1234'}
-        balancer = LoadBalancer(
-            id='234',
-            name='test',
-            state=State.RUNNING,
-            ip='1.2.3.4',
-            port=1234,
-            driver=self.driver,
-            extra=extra
-        )
-        members = self.driver.balancer_list_members(balancer)
-        self.assertEqual(2, len(members))
-        self.assertEqual(members[0].ip, '10.0.3.13')
-        self.assertEqual(members[0].id, '3dd806a2-c2c8-4c0c-9a4f-5219ea9266c0')
-        self.assertEqual(members[0].port, 9889)
-
-    def test_balancer_attach_member(self):
-        extra = {'pool_id': '4d360b1f-bc2c-4ab7-9884-1f03ba2768f7',
-                 'network_domain_id': '1234'}
-        balancer = LoadBalancer(
-            id='234',
-            name='test',
-            state=State.RUNNING,
-            ip='1.2.3.4',
-            port=1234,
-            driver=self.driver,
-            extra=extra
-        )
-        member = Member(
-            id=None,
-            ip='112.12.2.2',
-            port=80,
-            balancer=balancer,
-            extra=None)
-        member = self.driver.balancer_attach_member(balancer, member)
-        self.assertEqual(member.id, '3dd806a2-c2c8-4c0c-9a4f-5219ea9266c0')
-
-    def test_balancer_attach_member_without_port(self):
-        extra = {'pool_id': '4d360b1f-bc2c-4ab7-9884-1f03ba2768f7',
-                 'network_domain_id': '1234'}
-        balancer = LoadBalancer(
-            id='234',
-            name='test',
-            state=State.RUNNING,
-            ip='1.2.3.4',
-            port=1234,
-            driver=self.driver,
-            extra=extra
-        )
-        member = Member(
-            id=None,
-            ip='112.12.2.2',
-            port=None,
-            balancer=balancer,
-            extra=None)
-        member = self.driver.balancer_attach_member(balancer, member)
-        self.assertEqual(member.id, '3dd806a2-c2c8-4c0c-9a4f-5219ea9266c0')
-        self.assertEqual(member.port, None)
-
-    def test_balancer_detach_member(self):
-        extra = {'pool_id': '4d360b1f-bc2c-4ab7-9884-1f03ba2768f7',
-                 'network_domain_id': '1234'}
-        balancer = LoadBalancer(
-            id='234',
-            name='test',
-            state=State.RUNNING,
-            ip='1.2.3.4',
-            port=1234,
-            driver=self.driver,
-            extra=extra
-        )
-        member = Member(
-            id='3dd806a2-c2c8-4c0c-9a4f-5219ea9266c0',
-            ip='112.12.2.2',
-            port=80,
-            balancer=balancer,
-            extra=None)
-        result = self.driver.balancer_detach_member(balancer, member)
-        self.assertEqual(result, True)
-
-    def test_destroy_balancer(self):
-        extra = {'pool_id': '4d360b1f-bc2c-4ab7-9884-1f03ba2768f7',
-                 'network_domain_id': '1234'}
-        balancer = LoadBalancer(
-            id='234',
-            name='test',
-            state=State.RUNNING,
-            ip='1.2.3.4',
-            port=1234,
-            driver=self.driver,
-            extra=extra
-        )
-        response = self.driver.destroy_balancer(balancer)
-        self.assertEqual(response, True)
-
-    def test_set_get_network_domain_id(self):
-        self.driver.ex_set_current_network_domain('1234')
-        nwd = self.driver.ex_get_current_network_domain()
-        self.assertEqual(nwd, '1234')
-
-    def test_ex_create_pool_member(self):
-        pool = DimensionDataPool(
-            id='4d360b1f-bc2c-4ab7-9884-1f03ba2768f7',
-            name='test',
-            description='test',
-            status=State.RUNNING,
-            health_monitor_id=None,
-            load_balance_method=None,
-            service_down_action=None,
-            slow_ramp_time=None
-        )
-        node = DimensionDataVIPNode(
-            id='2344',
-            name='test',
-            status=State.RUNNING,
-            ip='123.23.3.2'
-        )
-        member = self.driver.ex_create_pool_member(
-            pool=pool,
-            node=node,
-            port=80
-        )
-        self.assertEqual(member.id, '3dd806a2-c2c8-4c0c-9a4f-5219ea9266c0')
-        self.assertEqual(member.name, '10.0.3.13')
-        self.assertEqual(member.ip, '123.23.3.2')
-
-    def test_ex_create_node(self):
-        node = self.driver.ex_create_node(
-            network_domain_id='12345',
-            name='test',
-            ip='123.12.32.2',
-            ex_description='',
-            connection_limit=25000,
-            connection_rate_limit=2000)
-        self.assertEqual(node.name, 'myProductionNode.1')
-        self.assertEqual(node.id, '9e6b496d-5261-4542-91aa-b50c7f569c54')
-
-    def test_ex_create_pool(self, ):
-        pool = self.driver.ex_create_pool(
-            network_domain_id='1234',
-            name='test',
-            balancer_method='ROUND_ROBIN',
-            ex_description='test',
-            service_down_action='NONE',
-            slow_ramp_time=30)
-        self.assertEqual(pool.id, '9e6b496d-5261-4542-91aa-b50c7f569c54')
-        self.assertEqual(pool.name, 'test')
-        self.assertEqual(pool.status, State.RUNNING)
-
-    def test_ex_create_virtual_listener(self):
-        listener = self.driver.ex_create_virtual_listener(
-            network_domain_id='12345',
-            name='test',
-            ex_description='test',
-            port=80,
-            pool=DimensionDataPool(
-                id='1234',
-                name='test',
-                description='test',
-                status=State.RUNNING,
-                health_monitor_id=None,
-                load_balance_method=None,
-                service_down_action=None,
-                slow_ramp_time=None
-            ))
-        self.assertEqual(listener.id, '8334f461-0df0-42d5-97eb-f4678eb26bea')
-        self.assertEqual(listener.name, 'test')
-
-    def test_ex_create_virtual_listener_unusual_port(self):
-        listener = self.driver.ex_create_virtual_listener(
-            network_domain_id='12345',
-            name='test',
-            ex_description='test',
-            port=8900,
-            pool=DimensionDataPool(
-                id='1234',
-                name='test',
-                description='test',
-                status=State.RUNNING,
-                health_monitor_id=None,
-                load_balance_method=None,
-                service_down_action=None,
-                slow_ramp_time=None
-            ))
-        self.assertEqual(listener.id, '8334f461-0df0-42d5-97eb-f4678eb26bea')
-        self.assertEqual(listener.name, 'test')
-
-    def test_ex_create_virtual_listener_without_port(self):
-        listener = self.driver.ex_create_virtual_listener(
-            network_domain_id='12345',
-            name='test',
-            ex_description='test',
-            pool=DimensionDataPool(
-                id='1234',
-                name='test',
-                description='test',
-                status=State.RUNNING,
-                health_monitor_id=None,
-                load_balance_method=None,
-                service_down_action=None,
-                slow_ramp_time=None
-            ))
-        self.assertEqual(listener.id, '8334f461-0df0-42d5-97eb-f4678eb26bea')
-        self.assertEqual(listener.name, 'test')
-
-    def test_ex_create_virtual_listener_without_pool(self):
-        listener = self.driver.ex_create_virtual_listener(
-            network_domain_id='12345',
-            name='test',
-            ex_description='test')
-        self.assertEqual(listener.id, '8334f461-0df0-42d5-97eb-f4678eb26bea')
-        self.assertEqual(listener.name, 'test')
-
-    def test_get_balancer(self):
-        bal = self.driver.get_balancer('6115469d-a8bb-445b-bb23-d23b5283f2b9')
-        self.assertEqual(bal.name, 'myProduction.Virtual.Listener')
-        self.assertEqual(bal.id, '6115469d-a8bb-445b-bb23-d23b5283f2b9')
-        self.assertEqual(bal.port, '8899')
-        self.assertEqual(bal.ip, '165.180.12.22')
-        self.assertEqual(bal.state, State.RUNNING)
-
-    def test_list_protocols(self):
-        protocols = self.driver.list_protocols()
-        self.assertNotEqual(0, len(protocols))
-
-    def test_ex_get_nodes(self):
-        nodes = self.driver.ex_get_nodes()
-        self.assertEqual(2, len(nodes))
-        self.assertEqual(nodes[0].name, 'ProductionNode.1')
-        self.assertEqual(nodes[0].id, '34de6ed6-46a4-4dae-a753-2f8d3840c6f9')
-        self.assertEqual(nodes[0].ip, '10.10.10.101')
-
-    def test_ex_get_node(self):
-        node = self.driver.ex_get_node('34de6ed6-46a4-4dae-a753-2f8d3840c6f9')
-        self.assertEqual(node.name, 'ProductionNode.2')
-        self.assertEqual(node.id, '34de6ed6-46a4-4dae-a753-2f8d3840c6f9')
-        self.assertEqual(node.ip, '10.10.10.101')
-
-    def test_ex_update_node(self):
-        node = self.driver.ex_get_node('34de6ed6-46a4-4dae-a753-2f8d3840c6f9')
-        node.connection_limit = '100'
-        result = self.driver.ex_update_node(node)
-        self.assertEqual(result.connection_limit, '100')
-
-    def test_ex_destroy_node(self):
-        result = self.driver.ex_destroy_node('34de6ed6-46a4-4dae-a753-2f8d3840c6f9')
-        self.assertTrue(result)
-
-    def test_ex_set_node_state(self):
-        node = self.driver.ex_get_node('34de6ed6-46a4-4dae-a753-2f8d3840c6f9')
-        result = self.driver.ex_set_node_state(node, False)
-        self.assertEqual(result.connection_limit, '10000')
-
-    def test_ex_get_pools(self):
-        pools = self.driver.ex_get_pools()
-        self.assertNotEqual(0, len(pools))
-        self.assertEqual(pools[0].name, 'myDevelopmentPool.1')
-        self.assertEqual(pools[0].id, '4d360b1f-bc2c-4ab7-9884-1f03ba2768f7')
-
-    def test_ex_get_pool(self):
-        pool = self.driver.ex_get_pool('4d360b1f-bc2c-4ab7-9884-1f03ba2768f7')
-        self.assertEqual(pool.name, 'myDevelopmentPool.1')
-        self.assertEqual(pool.id, '4d360b1f-bc2c-4ab7-9884-1f03ba2768f7')
-
-    def test_ex_update_pool(self):
-        pool = self.driver.ex_get_pool('4d360b1f-bc2c-4ab7-9884-1f03ba2768f7')
-        pool.slow_ramp_time = '120'
-        result = self.driver.ex_update_pool(pool)
-        self.assertTrue(result)
-
-    def test_ex_destroy_pool(self):
-        response = self.driver.ex_destroy_pool(
-            pool=DimensionDataPool(
-                id='4d360b1f-bc2c-4ab7-9884-1f03ba2768f7',
-                name='test',
-                description='test',
-                status=State.RUNNING,
-                health_monitor_id=None,
-                load_balance_method=None,
-                service_down_action=None,
-                slow_ramp_time=None))
-        self.assertTrue(response)
-
-    def test_get_pool_members(self):
-        members = self.driver.ex_get_pool_members('4d360b1f-bc2c-4ab7-9884-1f03ba2768f7')
-        self.assertEqual(2, len(members))
-        self.assertEqual(members[0].id, '3dd806a2-c2c8-4c0c-9a4f-5219ea9266c0')
-        self.assertEqual(members[0].name, '10.0.3.13')
-        self.assertEqual(members[0].status, 'NORMAL')
-        self.assertEqual(members[0].ip, '10.0.3.13')
-        self.assertEqual(members[0].port, 9889)
-        self.assertEqual(members[0].node_id, '3c207269-e75e-11e4-811f-005056806999')
-
-    def test_get_pool_member(self):
-        member = self.driver.ex_get_pool_member('3dd806a2-c2c8-4c0c-9a4f-5219ea9266c0')
-        self.assertEqual(member.id, '3dd806a2-c2c8-4c0c-9a4f-5219ea9266c0')
-        self.assertEqual(member.name, '10.0.3.13')
-        self.assertEqual(member.status, 'NORMAL')
-        self.assertEqual(member.ip, '10.0.3.13')
-        self.assertEqual(member.port, 9889)
-
-    def test_set_pool_member_state(self):
-        member = self.driver.ex_get_pool_member('3dd806a2-c2c8-4c0c-9a4f-5219ea9266c0')
-        result = self.driver.ex_set_pool_member_state(member, True)
-        self.assertTrue(result)
-
-    def test_ex_destroy_pool_member(self):
-        response = self.driver.ex_destroy_pool_member(
-            member=DimensionDataPoolMember(
-                id='',
-                name='test',
-                status=State.RUNNING,
-                ip='1.2.3.4',
-                port=80,
-                node_id='3c207269-e75e-11e4-811f-005056806999'),
-            destroy_node=False)
-        self.assertTrue(response)
-
-    def test_ex_destroy_pool_member_with_node(self):
-        response = self.driver.ex_destroy_pool_member(
-            member=DimensionDataPoolMember(
-                id='',
-                name='test',
-                status=State.RUNNING,
-                ip='1.2.3.4',
-                port=80,
-                node_id='34de6ed6-46a4-4dae-a753-2f8d3840c6f9'),
-            destroy_node=True)
-        self.assertTrue(response)
-
-    def test_ex_get_default_health_monitors(self):
-        monitors = self.driver.ex_get_default_health_monitors(
-            '4d360b1f-bc2c-4ab7-9884-1f03ba2768f7'
-        )
-        self.assertEqual(len(monitors), 6)
-        self.assertEqual(monitors[0].id, '01683574-d487-11e4-811f-005056806999')
-        self.assertEqual(monitors[0].name, 'CCDEFAULT.Http')
-        self.assertFalse(monitors[0].node_compatible)
-        self.assertTrue(monitors[0].pool_compatible)
-
-    def test_ex_get_default_persistence_profiles(self):
-        profiles = self.driver.ex_get_default_persistence_profiles(
-            '4d360b1f-bc2c-4ab7-9884-1f03ba2768f7'
-        )
-        self.assertEqual(len(profiles), 4)
-        self.assertEqual(profiles[0].id, 'a34ca024-f3db-11e4-b010-005056806999')
-        self.assertEqual(profiles[0].name, 'CCDEFAULT.Cookie')
-        self.assertEqual(profiles[0].fallback_compatible, False)
-        self.assertEqual(len(profiles[0].compatible_listeners), 1)
-        self.assertEqual(profiles[0].compatible_listeners[0].type, 'PERFORMANCE_LAYER_4')
-
-    def test_ex_get_default_irules(self):
-        irules = self.driver.ex_get_default_irules(
-            '4d360b1f-bc2c-4ab7-9884-1f03ba2768f7'
-        )
-        self.assertEqual(len(irules), 4)
-        self.assertEqual(irules[0].id, '2b20cb2c-ffdc-11e4-b010-005056806999')
-        self.assertEqual(irules[0].name, 'CCDEFAULT.HttpsRedirect')
-        self.assertEqual(len(irules[0].compatible_listeners), 1)
-        self.assertEqual(irules[0].compatible_listeners[0].type, 'PERFORMANCE_LAYER_4')
-
-
-class DimensionDataMockHttp(MockHttp):
-
-    fixtures = LoadBalancerFileFixtures('dimensiondata')
-
-    def _oec_0_9_myaccount_UNAUTHORIZED(self, method, url, body, headers):
-        return (httplib.UNAUTHORIZED, "", {}, httplib.responses[httplib.UNAUTHORIZED])
-
-    def _oec_0_9_myaccount(self, method, url, body, headers):
-        body = self.fixtures.load('oec_0_9_myaccount.xml')
-        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
-
-    def _oec_0_9_myaccount_INPROGRESS(self, method, url, body, headers):
-        body = self.fixtures.load('oec_0_9_myaccount.xml')
-        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
-
-    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_virtualListener(self, method, url, body, headers):
-        body = self.fixtures.load(
-            'networkDomainVip_virtualListener.xml')
-        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
-
-    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_virtualListener_6115469d_a8bb_445b_bb23_d23b5283f2b9(self, method, url, body, headers):
-        body = self.fixtures.load(
-            'networkDomainVip_virtualListener_6115469d_a8bb_445b_bb23_d23b5283f2b9.xml')
-        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
-
-    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_pool(self, method, url, body, headers):
-        body = self.fixtures.load(
-            'networkDomainVip_pool.xml')
-        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
-
-    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_pool_4d360b1f_bc2c_4ab7_9884_1f03ba2768f7(self, method, url, body, headers):
-        body = self.fixtures.load(
-            'networkDomainVip_pool_4d360b1f_bc2c_4ab7_9884_1f03ba2768f7.xml')
-        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
-
-    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_poolMember(self, method, url, body, headers):
-        body = self.fixtures.load(
-            'networkDomainVip_poolMember.xml')
-        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
-
-    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_poolMember_3dd806a2_c2c8_4c0c_9a4f_5219ea9266c0(self, method, url, body, headers):
-        body = self.fixtures.load(
-            'networkDomainVip_poolMember_3dd806a2_c2c8_4c0c_9a4f_5219ea9266c0.xml')
-        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
-
-    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_createPool(self, method, url, body, headers):
-        body = self.fixtures.load(
-            'networkDomainVip_createPool.xml')
-        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
-
-    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_createNode(self, method, url, body, headers):
-        body = self.fixtures.load(
-            'networkDomainVip_createNode.xml')
-        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
-
-    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_addPoolMember(self, method, url, body, headers):
-        body = self.fixtures.load(
-            'networkDomainVip_addPoolMember.xml')
-        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
-
-    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_createVirtualListener(self, method, url, body, headers):
-        body = self.fixtures.load(
-            'networkDomainVip_createVirtualListener.xml')
-        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
-
-    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_removePoolMember(self, method, url, body, headers):
-        body = self.fixtures.load(
-            'networkDomainVip_removePoolMember.xml')
-        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
-
-    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_deleteVirtualListener(self, method, url, body, headers):
-        body = self.fixtures.load(
-            'networkDomainVip_deleteVirtualListener.xml')
-        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
-
-    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_deletePool(self, method, url, body, headers):
-        body = self.fixtures.load(
-            'networkDomainVip_deletePool.xml')
-        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
-
-    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_deleteNode(self, method, url, body, headers):
-        body = self.fixtures.load(
-            'networkDomainVip_deleteNode.xml')
-        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
-
-    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_node(self, method, url, body, headers):
-        body = self.fixtures.load(
-            'networkDomainVip_node.xml')
-        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
-
-    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_node_34de6ed6_46a4_4dae_a753_2f8d3840c6f9(self, method, url, body, headers):
-        body = self.fixtures.load(
-            'networkDomainVip_node_34de6ed6_46a4_4dae_a753_2f8d3840c6f9.xml')
-        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
-
-    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_editNode(self, method, url, body, headers):
-        body = self.fixtures.load(
-            'networkDomainVip_editNode.xml')
-        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
-
-    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_editPool(self, method, url, body, headers):
-        body = self.fixtures.load(
-            'networkDomainVip_editPool.xml')
-        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
-
-    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_editPoolMember(self, method, url, body, headers):
-        body = self.fixtures.load(
-            'networkDomainVip_editPoolMember.xml')
-        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
-
-    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_defaultHealthMonitor(self, method, url, body, headers):
-        body = self.fixtures.load(
-            'networkDomainVip_defaultHealthMonitor.xml')
-        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
-
-    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_defaultPersistenceProfile(self, method, url, body, headers):
-        body = self.fixtures.load(
-            'networkDomainVip_defaultPersistenceProfile.xml')
-        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
-
-    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_defaultIrule(self, method, url, body, headers):
-        body = self.fixtures.load(
-            'networkDomainVip_defaultIrule.xml')
-        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
-
-if __name__ == '__main__':
-    sys.exit(unittest.main())

http://git-wip-us.apache.org/repos/asf/libcloud/blob/bb1b8104/libcloud/test/loadbalancer/test_dimensiondata_v2_3.py
----------------------------------------------------------------------
diff --git a/libcloud/test/loadbalancer/test_dimensiondata_v2_3.py b/libcloud/test/loadbalancer/test_dimensiondata_v2_3.py
new file mode 100644
index 0000000..c609e3d
--- /dev/null
+++ b/libcloud/test/loadbalancer/test_dimensiondata_v2_3.py
@@ -0,0 +1,620 @@
+# 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.
+import sys
+from libcloud.utils.py3 import httplib
+
+from libcloud.common.types import InvalidCredsError
+from libcloud.common.dimensiondata import DimensionDataVIPNode, DimensionDataPool
+from libcloud.common.dimensiondata import DimensionDataPoolMember
+from libcloud.loadbalancer.base import LoadBalancer, Member, Algorithm
+from libcloud.loadbalancer.drivers.dimensiondata \
+    import DimensionDataLBDriver as DimensionData
+from libcloud.loadbalancer.types import State
+
+from libcloud.test import MockHttp, unittest
+from libcloud.test.file_fixtures import LoadBalancerFileFixtures
+
+from libcloud.test.secrets import DIMENSIONDATA_PARAMS
+
+
+class DimensionDataTests(unittest.TestCase):
+
+    def setUp(self):
+        DimensionData.connectionCls.active_api_version = '2.3'
+        DimensionData.connectionCls.conn_classes = (None, DimensionDataMockHttp)
+        DimensionDataMockHttp.type = None
+        self.driver = DimensionData(*DIMENSIONDATA_PARAMS)
+
+    def test_invalid_region(self):
+        with self.assertRaises(ValueError):
+            self.driver = DimensionData(*DIMENSIONDATA_PARAMS, region='blah')
+
+    def test_invalid_creds(self):
+        DimensionDataMockHttp.type = 'UNAUTHORIZED'
+        with self.assertRaises(InvalidCredsError):
+            self.driver.list_balancers()
+
+    def test_create_balancer(self):
+        self.driver.ex_set_current_network_domain('1234')
+        members = []
+        members.append(Member(
+            id=None,
+            ip='1.2.3.4',
+            port=80))
+
+        balancer = self.driver.create_balancer(
+            name='test',
+            port=80,
+            protocol='http',
+            algorithm=Algorithm.ROUND_ROBIN,
+            members=members,
+            ex_listener_ip_address='5.6.7.8')
+        self.assertEqual(balancer.name, 'test')
+        self.assertEqual(balancer.id, '8334f461-0df0-42d5-97eb-f4678eb26bea')
+        self.assertEqual(balancer.ip, '165.180.12.22')
+        self.assertEqual(balancer.port, 80)
+        self.assertEqual(balancer.extra['pool_id'], '9e6b496d-5261-4542-91aa-b50c7f569c54')
+        self.assertEqual(balancer.extra['network_domain_id'], '1234')
+        self.assertEqual(balancer.extra['listener_ip_address'], '5.6.7.8')
+
+    def test_create_balancer_with_defaults(self):
+        self.driver.ex_set_current_network_domain('1234')
+
+        balancer = self.driver.create_balancer(
+            name='test',
+            port=None,
+            protocol=None,
+            algorithm=None,
+            members=None)
+        self.assertEqual(balancer.name, 'test')
+        self.assertEqual(balancer.id, '8334f461-0df0-42d5-97eb-f4678eb26bea')
+        self.assertEqual(balancer.ip, '165.180.12.22')
+        self.assertEqual(balancer.port, None)
+        self.assertEqual(balancer.extra['pool_id'], '9e6b496d-5261-4542-91aa-b50c7f569c54')
+        self.assertEqual(balancer.extra['network_domain_id'], '1234')
+
+    def test_create_balancer_no_members(self):
+        self.driver.ex_set_current_network_domain('1234')
+        members = None
+
+        balancer = self.driver.create_balancer(
+            name='test',
+            port=80,
+            protocol='http',
+            algorithm=Algorithm.ROUND_ROBIN,
+            members=members)
+        self.assertEqual(balancer.name, 'test')
+        self.assertEqual(balancer.id, '8334f461-0df0-42d5-97eb-f4678eb26bea')
+        self.assertEqual(balancer.ip, '165.180.12.22')
+        self.assertEqual(balancer.port, 80)
+        self.assertEqual(balancer.extra['pool_id'], '9e6b496d-5261-4542-91aa-b50c7f569c54')
+        self.assertEqual(balancer.extra['network_domain_id'], '1234')
+
+    def test_create_balancer_empty_members(self):
+        self.driver.ex_set_current_network_domain('1234')
+        members = []
+
+        balancer = self.driver.create_balancer(
+            name='test',
+            port=80,
+            protocol='http',
+            algorithm=Algorithm.ROUND_ROBIN,
+            members=members)
+        self.assertEqual(balancer.name, 'test')
+        self.assertEqual(balancer.id, '8334f461-0df0-42d5-97eb-f4678eb26bea')
+        self.assertEqual(balancer.ip, '165.180.12.22')
+        self.assertEqual(balancer.port, 80)
+        self.assertEqual(balancer.extra['pool_id'], '9e6b496d-5261-4542-91aa-b50c7f569c54')
+        self.assertEqual(balancer.extra['network_domain_id'], '1234')
+
+    def test_list_balancers(self):
+        bal = self.driver.list_balancers()
+        self.assertEqual(bal[0].name, 'myProduction.Virtual.Listener')
+        self.assertEqual(bal[0].id, '6115469d-a8bb-445b-bb23-d23b5283f2b9')
+        self.assertEqual(bal[0].port, '8899')
+        self.assertEqual(bal[0].ip, '165.180.12.22')
+        self.assertEqual(bal[0].state, State.RUNNING)
+
+    def test_balancer_list_members(self):
+        extra = {'pool_id': '4d360b1f-bc2c-4ab7-9884-1f03ba2768f7',
+                 'network_domain_id': '1234'}
+        balancer = LoadBalancer(
+            id='234',
+            name='test',
+            state=State.RUNNING,
+            ip='1.2.3.4',
+            port=1234,
+            driver=self.driver,
+            extra=extra
+        )
+        members = self.driver.balancer_list_members(balancer)
+        self.assertEqual(2, len(members))
+        self.assertEqual(members[0].ip, '10.0.3.13')
+        self.assertEqual(members[0].id, '3dd806a2-c2c8-4c0c-9a4f-5219ea9266c0')
+        self.assertEqual(members[0].port, 9889)
+
+    def test_balancer_attach_member(self):
+        extra = {'pool_id': '4d360b1f-bc2c-4ab7-9884-1f03ba2768f7',
+                 'network_domain_id': '1234'}
+        balancer = LoadBalancer(
+            id='234',
+            name='test',
+            state=State.RUNNING,
+            ip='1.2.3.4',
+            port=1234,
+            driver=self.driver,
+            extra=extra
+        )
+        member = Member(
+            id=None,
+            ip='112.12.2.2',
+            port=80,
+            balancer=balancer,
+            extra=None)
+        member = self.driver.balancer_attach_member(balancer, member)
+        self.assertEqual(member.id, '3dd806a2-c2c8-4c0c-9a4f-5219ea9266c0')
+
+    def test_balancer_attach_member_without_port(self):
+        extra = {'pool_id': '4d360b1f-bc2c-4ab7-9884-1f03ba2768f7',
+                 'network_domain_id': '1234'}
+        balancer = LoadBalancer(
+            id='234',
+            name='test',
+            state=State.RUNNING,
+            ip='1.2.3.4',
+            port=1234,
+            driver=self.driver,
+            extra=extra
+        )
+        member = Member(
+            id=None,
+            ip='112.12.2.2',
+            port=None,
+            balancer=balancer,
+            extra=None)
+        member = self.driver.balancer_attach_member(balancer, member)
+        self.assertEqual(member.id, '3dd806a2-c2c8-4c0c-9a4f-5219ea9266c0')
+        self.assertEqual(member.port, None)
+
+    def test_balancer_detach_member(self):
+        extra = {'pool_id': '4d360b1f-bc2c-4ab7-9884-1f03ba2768f7',
+                 'network_domain_id': '1234'}
+        balancer = LoadBalancer(
+            id='234',
+            name='test',
+            state=State.RUNNING,
+            ip='1.2.3.4',
+            port=1234,
+            driver=self.driver,
+            extra=extra
+        )
+        member = Member(
+            id='3dd806a2-c2c8-4c0c-9a4f-5219ea9266c0',
+            ip='112.12.2.2',
+            port=80,
+            balancer=balancer,
+            extra=None)
+        result = self.driver.balancer_detach_member(balancer, member)
+        self.assertEqual(result, True)
+
+    def test_destroy_balancer(self):
+        extra = {'pool_id': '4d360b1f-bc2c-4ab7-9884-1f03ba2768f7',
+                 'network_domain_id': '1234'}
+        balancer = LoadBalancer(
+            id='234',
+            name='test',
+            state=State.RUNNING,
+            ip='1.2.3.4',
+            port=1234,
+            driver=self.driver,
+            extra=extra
+        )
+        response = self.driver.destroy_balancer(balancer)
+        self.assertEqual(response, True)
+
+    def test_set_get_network_domain_id(self):
+        self.driver.ex_set_current_network_domain('1234')
+        nwd = self.driver.ex_get_current_network_domain()
+        self.assertEqual(nwd, '1234')
+
+    def test_ex_create_pool_member(self):
+        pool = DimensionDataPool(
+            id='4d360b1f-bc2c-4ab7-9884-1f03ba2768f7',
+            name='test',
+            description='test',
+            status=State.RUNNING,
+            health_monitor_id=None,
+            load_balance_method=None,
+            service_down_action=None,
+            slow_ramp_time=None
+        )
+        node = DimensionDataVIPNode(
+            id='2344',
+            name='test',
+            status=State.RUNNING,
+            ip='123.23.3.2'
+        )
+        member = self.driver.ex_create_pool_member(
+            pool=pool,
+            node=node,
+            port=80
+        )
+        self.assertEqual(member.id, '3dd806a2-c2c8-4c0c-9a4f-5219ea9266c0')
+        self.assertEqual(member.name, '10.0.3.13')
+        self.assertEqual(member.ip, '123.23.3.2')
+
+    def test_ex_create_node(self):
+        node = self.driver.ex_create_node(
+            network_domain_id='12345',
+            name='test',
+            ip='123.12.32.2',
+            ex_description='',
+            connection_limit=25000,
+            connection_rate_limit=2000)
+        self.assertEqual(node.name, 'myProductionNode.1')
+        self.assertEqual(node.id, '9e6b496d-5261-4542-91aa-b50c7f569c54')
+
+    def test_ex_create_pool(self, ):
+        pool = self.driver.ex_create_pool(
+            network_domain_id='1234',
+            name='test',
+            balancer_method='ROUND_ROBIN',
+            ex_description='test',
+            service_down_action='NONE',
+            slow_ramp_time=30)
+        self.assertEqual(pool.id, '9e6b496d-5261-4542-91aa-b50c7f569c54')
+        self.assertEqual(pool.name, 'test')
+        self.assertEqual(pool.status, State.RUNNING)
+
+    def test_ex_create_virtual_listener(self):
+        listener = self.driver.ex_create_virtual_listener(
+            network_domain_id='12345',
+            name='test',
+            ex_description='test',
+            port=80,
+            pool=DimensionDataPool(
+                id='1234',
+                name='test',
+                description='test',
+                status=State.RUNNING,
+                health_monitor_id=None,
+                load_balance_method=None,
+                service_down_action=None,
+                slow_ramp_time=None
+            ))
+        self.assertEqual(listener.id, '8334f461-0df0-42d5-97eb-f4678eb26bea')
+        self.assertEqual(listener.name, 'test')
+
+    def test_ex_create_virtual_listener_unusual_port(self):
+        listener = self.driver.ex_create_virtual_listener(
+            network_domain_id='12345',
+            name='test',
+            ex_description='test',
+            port=8900,
+            pool=DimensionDataPool(
+                id='1234',
+                name='test',
+                description='test',
+                status=State.RUNNING,
+                health_monitor_id=None,
+                load_balance_method=None,
+                service_down_action=None,
+                slow_ramp_time=None
+            ))
+        self.assertEqual(listener.id, '8334f461-0df0-42d5-97eb-f4678eb26bea')
+        self.assertEqual(listener.name, 'test')
+
+    def test_ex_create_virtual_listener_without_port(self):
+        listener = self.driver.ex_create_virtual_listener(
+            network_domain_id='12345',
+            name='test',
+            ex_description='test',
+            pool=DimensionDataPool(
+                id='1234',
+                name='test',
+                description='test',
+                status=State.RUNNING,
+                health_monitor_id=None,
+                load_balance_method=None,
+                service_down_action=None,
+                slow_ramp_time=None
+            ))
+        self.assertEqual(listener.id, '8334f461-0df0-42d5-97eb-f4678eb26bea')
+        self.assertEqual(listener.name, 'test')
+
+    def test_ex_create_virtual_listener_without_pool(self):
+        listener = self.driver.ex_create_virtual_listener(
+            network_domain_id='12345',
+            name='test',
+            ex_description='test')
+        self.assertEqual(listener.id, '8334f461-0df0-42d5-97eb-f4678eb26bea')
+        self.assertEqual(listener.name, 'test')
+
+    def test_get_balancer(self):
+        bal = self.driver.get_balancer('6115469d-a8bb-445b-bb23-d23b5283f2b9')
+        self.assertEqual(bal.name, 'myProduction.Virtual.Listener')
+        self.assertEqual(bal.id, '6115469d-a8bb-445b-bb23-d23b5283f2b9')
+        self.assertEqual(bal.port, '8899')
+        self.assertEqual(bal.ip, '165.180.12.22')
+        self.assertEqual(bal.state, State.RUNNING)
+
+    def test_list_protocols(self):
+        protocols = self.driver.list_protocols()
+        self.assertNotEqual(0, len(protocols))
+
+    def test_ex_get_nodes(self):
+        nodes = self.driver.ex_get_nodes()
+        self.assertEqual(2, len(nodes))
+        self.assertEqual(nodes[0].name, 'ProductionNode.1')
+        self.assertEqual(nodes[0].id, '34de6ed6-46a4-4dae-a753-2f8d3840c6f9')
+        self.assertEqual(nodes[0].ip, '10.10.10.101')
+
+    def test_ex_get_node(self):
+        node = self.driver.ex_get_node('34de6ed6-46a4-4dae-a753-2f8d3840c6f9')
+        self.assertEqual(node.name, 'ProductionNode.2')
+        self.assertEqual(node.id, '34de6ed6-46a4-4dae-a753-2f8d3840c6f9')
+        self.assertEqual(node.ip, '10.10.10.101')
+
+    def test_ex_update_node(self):
+        node = self.driver.ex_get_node('34de6ed6-46a4-4dae-a753-2f8d3840c6f9')
+        node.connection_limit = '100'
+        result = self.driver.ex_update_node(node)
+        self.assertEqual(result.connection_limit, '100')
+
+    def test_ex_destroy_node(self):
+        result = self.driver.ex_destroy_node('34de6ed6-46a4-4dae-a753-2f8d3840c6f9')
+        self.assertTrue(result)
+
+    def test_ex_set_node_state(self):
+        node = self.driver.ex_get_node('34de6ed6-46a4-4dae-a753-2f8d3840c6f9')
+        result = self.driver.ex_set_node_state(node, False)
+        self.assertEqual(result.connection_limit, '10000')
+
+    def test_ex_get_pools(self):
+        pools = self.driver.ex_get_pools()
+        self.assertNotEqual(0, len(pools))
+        self.assertEqual(pools[0].name, 'myDevelopmentPool.1')
+        self.assertEqual(pools[0].id, '4d360b1f-bc2c-4ab7-9884-1f03ba2768f7')
+
+    def test_ex_get_pool(self):
+        pool = self.driver.ex_get_pool('4d360b1f-bc2c-4ab7-9884-1f03ba2768f7')
+        self.assertEqual(pool.name, 'myDevelopmentPool.1')
+        self.assertEqual(pool.id, '4d360b1f-bc2c-4ab7-9884-1f03ba2768f7')
+
+    def test_ex_update_pool(self):
+        pool = self.driver.ex_get_pool('4d360b1f-bc2c-4ab7-9884-1f03ba2768f7')
+        pool.slow_ramp_time = '120'
+        result = self.driver.ex_update_pool(pool)
+        self.assertTrue(result)
+
+    def test_ex_destroy_pool(self):
+        response = self.driver.ex_destroy_pool(
+            pool=DimensionDataPool(
+                id='4d360b1f-bc2c-4ab7-9884-1f03ba2768f7',
+                name='test',
+                description='test',
+                status=State.RUNNING,
+                health_monitor_id=None,
+                load_balance_method=None,
+                service_down_action=None,
+                slow_ramp_time=None))
+        self.assertTrue(response)
+
+    def test_get_pool_members(self):
+        members = self.driver.ex_get_pool_members('4d360b1f-bc2c-4ab7-9884-1f03ba2768f7')
+        self.assertEqual(2, len(members))
+        self.assertEqual(members[0].id, '3dd806a2-c2c8-4c0c-9a4f-5219ea9266c0')
+        self.assertEqual(members[0].name, '10.0.3.13')
+        self.assertEqual(members[0].status, 'NORMAL')
+        self.assertEqual(members[0].ip, '10.0.3.13')
+        self.assertEqual(members[0].port, 9889)
+        self.assertEqual(members[0].node_id, '3c207269-e75e-11e4-811f-005056806999')
+
+    def test_get_pool_member(self):
+        member = self.driver.ex_get_pool_member('3dd806a2-c2c8-4c0c-9a4f-5219ea9266c0')
+        self.assertEqual(member.id, '3dd806a2-c2c8-4c0c-9a4f-5219ea9266c0')
+        self.assertEqual(member.name, '10.0.3.13')
+        self.assertEqual(member.status, 'NORMAL')
+        self.assertEqual(member.ip, '10.0.3.13')
+        self.assertEqual(member.port, 9889)
+
+    def test_set_pool_member_state(self):
+        member = self.driver.ex_get_pool_member('3dd806a2-c2c8-4c0c-9a4f-5219ea9266c0')
+        result = self.driver.ex_set_pool_member_state(member, True)
+        self.assertTrue(result)
+
+    def test_ex_destroy_pool_member(self):
+        response = self.driver.ex_destroy_pool_member(
+            member=DimensionDataPoolMember(
+                id='',
+                name='test',
+                status=State.RUNNING,
+                ip='1.2.3.4',
+                port=80,
+                node_id='3c207269-e75e-11e4-811f-005056806999'),
+            destroy_node=False)
+        self.assertTrue(response)
+
+    def test_ex_destroy_pool_member_with_node(self):
+        response = self.driver.ex_destroy_pool_member(
+            member=DimensionDataPoolMember(
+                id='',
+                name='test',
+                status=State.RUNNING,
+                ip='1.2.3.4',
+                port=80,
+                node_id='34de6ed6-46a4-4dae-a753-2f8d3840c6f9'),
+            destroy_node=True)
+        self.assertTrue(response)
+
+    def test_ex_get_default_health_monitors(self):
+        monitors = self.driver.ex_get_default_health_monitors(
+            '4d360b1f-bc2c-4ab7-9884-1f03ba2768f7'
+        )
+        self.assertEqual(len(monitors), 6)
+        self.assertEqual(monitors[0].id, '01683574-d487-11e4-811f-005056806999')
+        self.assertEqual(monitors[0].name, 'CCDEFAULT.Http')
+        self.assertFalse(monitors[0].node_compatible)
+        self.assertTrue(monitors[0].pool_compatible)
+
+    def test_ex_get_default_persistence_profiles(self):
+        profiles = self.driver.ex_get_default_persistence_profiles(
+            '4d360b1f-bc2c-4ab7-9884-1f03ba2768f7'
+        )
+        self.assertEqual(len(profiles), 4)
+        self.assertEqual(profiles[0].id, 'a34ca024-f3db-11e4-b010-005056806999')
+        self.assertEqual(profiles[0].name, 'CCDEFAULT.Cookie')
+        self.assertEqual(profiles[0].fallback_compatible, False)
+        self.assertEqual(len(profiles[0].compatible_listeners), 1)
+        self.assertEqual(profiles[0].compatible_listeners[0].type, 'PERFORMANCE_LAYER_4')
+
+    def test_ex_get_default_irules(self):
+        irules = self.driver.ex_get_default_irules(
+            '4d360b1f-bc2c-4ab7-9884-1f03ba2768f7'
+        )
+        self.assertEqual(len(irules), 4)
+        self.assertEqual(irules[0].id, '2b20cb2c-ffdc-11e4-b010-005056806999')
+        self.assertEqual(irules[0].name, 'CCDEFAULT.HttpsRedirect')
+        self.assertEqual(len(irules[0].compatible_listeners), 1)
+        self.assertEqual(irules[0].compatible_listeners[0].type, 'PERFORMANCE_LAYER_4')
+
+
+class DimensionDataMockHttp(MockHttp):
+
+    fixtures = LoadBalancerFileFixtures('dimensiondata')
+
+    def _oec_0_9_myaccount_UNAUTHORIZED(self, method, url, body, headers):
+        return (httplib.UNAUTHORIZED, "", {}, httplib.responses[httplib.UNAUTHORIZED])
+
+    def _oec_0_9_myaccount(self, method, url, body, headers):
+        body = self.fixtures.load('oec_0_9_myaccount.xml')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+    def _oec_0_9_myaccount_INPROGRESS(self, method, url, body, headers):
+        body = self.fixtures.load('oec_0_9_myaccount.xml')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_virtualListener(self, method, url, body, headers):
+        body = self.fixtures.load(
+            'networkDomainVip_virtualListener.xml')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_virtualListener_6115469d_a8bb_445b_bb23_d23b5283f2b9(self, method, url, body, headers):
+        body = self.fixtures.load(
+            'networkDomainVip_virtualListener_6115469d_a8bb_445b_bb23_d23b5283f2b9.xml')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_pool(self, method, url, body, headers):
+        body = self.fixtures.load(
+            'networkDomainVip_pool.xml')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_pool_4d360b1f_bc2c_4ab7_9884_1f03ba2768f7(self, method, url, body, headers):
+        body = self.fixtures.load(
+            'networkDomainVip_pool_4d360b1f_bc2c_4ab7_9884_1f03ba2768f7.xml')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_poolMember(self, method, url, body, headers):
+        body = self.fixtures.load(
+            'networkDomainVip_poolMember.xml')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_poolMember_3dd806a2_c2c8_4c0c_9a4f_5219ea9266c0(self, method, url, body, headers):
+        body = self.fixtures.load(
+            'networkDomainVip_poolMember_3dd806a2_c2c8_4c0c_9a4f_5219ea9266c0.xml')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_createPool(self, method, url, body, headers):
+        body = self.fixtures.load(
+            'networkDomainVip_createPool.xml')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_createNode(self, method, url, body, headers):
+        body = self.fixtures.load(
+            'networkDomainVip_createNode.xml')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_addPoolMember(self, method, url, body, headers):
+        body = self.fixtures.load(
+            'networkDomainVip_addPoolMember.xml')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_createVirtualListener(self, method, url, body, headers):
+        body = self.fixtures.load(
+            'networkDomainVip_createVirtualListener.xml')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_removePoolMember(self, method, url, body, headers):
+        body = self.fixtures.load(
+            'networkDomainVip_removePoolMember.xml')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_deleteVirtualListener(self, method, url, body, headers):
+        body = self.fixtures.load(
+            'networkDomainVip_deleteVirtualListener.xml')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_deletePool(self, method, url, body, headers):
+        body = self.fixtures.load(
+            'networkDomainVip_deletePool.xml')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_deleteNode(self, method, url, body, headers):
+        body = self.fixtures.load(
+            'networkDomainVip_deleteNode.xml')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_node(self, method, url, body, headers):
+        body = self.fixtures.load(
+            'networkDomainVip_node.xml')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_node_34de6ed6_46a4_4dae_a753_2f8d3840c6f9(self, method, url, body, headers):
+        body = self.fixtures.load(
+            'networkDomainVip_node_34de6ed6_46a4_4dae_a753_2f8d3840c6f9.xml')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_editNode(self, method, url, body, headers):
+        body = self.fixtures.load(
+            'networkDomainVip_editNode.xml')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_editPool(self, method, url, body, headers):
+        body = self.fixtures.load(
+            'networkDomainVip_editPool.xml')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_editPoolMember(self, method, url, body, headers):
+        body = self.fixtures.load(
+            'networkDomainVip_editPoolMember.xml')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_defaultHealthMonitor(self, method, url, body, headers):
+        body = self.fixtures.load(
+            'networkDomainVip_defaultHealthMonitor.xml')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_defaultPersistenceProfile(self, method, url, body, headers):
+        body = self.fixtures.load(
+            'networkDomainVip_defaultPersistenceProfile.xml')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_defaultIrule(self, method, url, body, headers):
+        body = self.fixtures.load(
+            'networkDomainVip_defaultIrule.xml')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+if __name__ == '__main__':
+    sys.exit(unittest.main())

http://git-wip-us.apache.org/repos/asf/libcloud/blob/bb1b8104/libcloud/test/loadbalancer/test_dimensiondata_v2_4.py
----------------------------------------------------------------------
diff --git a/libcloud/test/loadbalancer/test_dimensiondata_v2_4.py b/libcloud/test/loadbalancer/test_dimensiondata_v2_4.py
new file mode 100644
index 0000000..e3f7217
--- /dev/null
+++ b/libcloud/test/loadbalancer/test_dimensiondata_v2_4.py
@@ -0,0 +1,620 @@
+# 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.
+import sys
+from libcloud.utils.py3 import httplib
+
+from libcloud.common.types import InvalidCredsError
+from libcloud.common.dimensiondata import DimensionDataVIPNode, DimensionDataPool
+from libcloud.common.dimensiondata import DimensionDataPoolMember
+from libcloud.loadbalancer.base import LoadBalancer, Member, Algorithm
+from libcloud.loadbalancer.drivers.dimensiondata \
+    import DimensionDataLBDriver as DimensionData
+from libcloud.loadbalancer.types import State
+
+from libcloud.test import MockHttp, unittest
+from libcloud.test.file_fixtures import LoadBalancerFileFixtures
+
+from libcloud.test.secrets import DIMENSIONDATA_PARAMS
+
+
+class DimensionDataTests(unittest.TestCase):
+
+    def setUp(self):
+        DimensionData.connectionCls.active_api_version = '2.4'
+        DimensionData.connectionCls.conn_classes = (None, DimensionDataMockHttp)
+        DimensionDataMockHttp.type = None
+        self.driver = DimensionData(*DIMENSIONDATA_PARAMS)
+
+    def test_invalid_region(self):
+        with self.assertRaises(ValueError):
+            self.driver = DimensionData(*DIMENSIONDATA_PARAMS, region='blah')
+
+    def test_invalid_creds(self):
+        DimensionDataMockHttp.type = 'UNAUTHORIZED'
+        with self.assertRaises(InvalidCredsError):
+            self.driver.list_balancers()
+
+    def test_create_balancer(self):
+        self.driver.ex_set_current_network_domain('1234')
+        members = []
+        members.append(Member(
+            id=None,
+            ip='1.2.3.4',
+            port=80))
+
+        balancer = self.driver.create_balancer(
+            name='test',
+            port=80,
+            protocol='http',
+            algorithm=Algorithm.ROUND_ROBIN,
+            members=members,
+            ex_listener_ip_address='5.6.7.8')
+        self.assertEqual(balancer.name, 'test')
+        self.assertEqual(balancer.id, '8334f461-0df0-42d5-97eb-f4678eb26bea')
+        self.assertEqual(balancer.ip, '165.180.12.22')
+        self.assertEqual(balancer.port, 80)
+        self.assertEqual(balancer.extra['pool_id'], '9e6b496d-5261-4542-91aa-b50c7f569c54')
+        self.assertEqual(balancer.extra['network_domain_id'], '1234')
+        self.assertEqual(balancer.extra['listener_ip_address'], '5.6.7.8')
+
+    def test_create_balancer_with_defaults(self):
+        self.driver.ex_set_current_network_domain('1234')
+
+        balancer = self.driver.create_balancer(
+            name='test',
+            port=None,
+            protocol=None,
+            algorithm=None,
+            members=None)
+        self.assertEqual(balancer.name, 'test')
+        self.assertEqual(balancer.id, '8334f461-0df0-42d5-97eb-f4678eb26bea')
+        self.assertEqual(balancer.ip, '165.180.12.22')
+        self.assertEqual(balancer.port, None)
+        self.assertEqual(balancer.extra['pool_id'], '9e6b496d-5261-4542-91aa-b50c7f569c54')
+        self.assertEqual(balancer.extra['network_domain_id'], '1234')
+
+    def test_create_balancer_no_members(self):
+        self.driver.ex_set_current_network_domain('1234')
+        members = None
+
+        balancer = self.driver.create_balancer(
+            name='test',
+            port=80,
+            protocol='http',
+            algorithm=Algorithm.ROUND_ROBIN,
+            members=members)
+        self.assertEqual(balancer.name, 'test')
+        self.assertEqual(balancer.id, '8334f461-0df0-42d5-97eb-f4678eb26bea')
+        self.assertEqual(balancer.ip, '165.180.12.22')
+        self.assertEqual(balancer.port, 80)
+        self.assertEqual(balancer.extra['pool_id'], '9e6b496d-5261-4542-91aa-b50c7f569c54')
+        self.assertEqual(balancer.extra['network_domain_id'], '1234')
+
+    def test_create_balancer_empty_members(self):
+        self.driver.ex_set_current_network_domain('1234')
+        members = []
+
+        balancer = self.driver.create_balancer(
+            name='test',
+            port=80,
+            protocol='http',
+            algorithm=Algorithm.ROUND_ROBIN,
+            members=members)
+        self.assertEqual(balancer.name, 'test')
+        self.assertEqual(balancer.id, '8334f461-0df0-42d5-97eb-f4678eb26bea')
+        self.assertEqual(balancer.ip, '165.180.12.22')
+        self.assertEqual(balancer.port, 80)
+        self.assertEqual(balancer.extra['pool_id'], '9e6b496d-5261-4542-91aa-b50c7f569c54')
+        self.assertEqual(balancer.extra['network_domain_id'], '1234')
+
+    def test_list_balancers(self):
+        bal = self.driver.list_balancers()
+        self.assertEqual(bal[0].name, 'myProduction.Virtual.Listener')
+        self.assertEqual(bal[0].id, '6115469d-a8bb-445b-bb23-d23b5283f2b9')
+        self.assertEqual(bal[0].port, '8899')
+        self.assertEqual(bal[0].ip, '165.180.12.22')
+        self.assertEqual(bal[0].state, State.RUNNING)
+
+    def test_balancer_list_members(self):
+        extra = {'pool_id': '4d360b1f-bc2c-4ab7-9884-1f03ba2768f7',
+                 'network_domain_id': '1234'}
+        balancer = LoadBalancer(
+            id='234',
+            name='test',
+            state=State.RUNNING,
+            ip='1.2.3.4',
+            port=1234,
+            driver=self.driver,
+            extra=extra
+        )
+        members = self.driver.balancer_list_members(balancer)
+        self.assertEqual(2, len(members))
+        self.assertEqual(members[0].ip, '10.0.3.13')
+        self.assertEqual(members[0].id, '3dd806a2-c2c8-4c0c-9a4f-5219ea9266c0')
+        self.assertEqual(members[0].port, 9889)
+
+    def test_balancer_attach_member(self):
+        extra = {'pool_id': '4d360b1f-bc2c-4ab7-9884-1f03ba2768f7',
+                 'network_domain_id': '1234'}
+        balancer = LoadBalancer(
+            id='234',
+            name='test',
+            state=State.RUNNING,
+            ip='1.2.3.4',
+            port=1234,
+            driver=self.driver,
+            extra=extra
+        )
+        member = Member(
+            id=None,
+            ip='112.12.2.2',
+            port=80,
+            balancer=balancer,
+            extra=None)
+        member = self.driver.balancer_attach_member(balancer, member)
+        self.assertEqual(member.id, '3dd806a2-c2c8-4c0c-9a4f-5219ea9266c0')
+
+    def test_balancer_attach_member_without_port(self):
+        extra = {'pool_id': '4d360b1f-bc2c-4ab7-9884-1f03ba2768f7',
+                 'network_domain_id': '1234'}
+        balancer = LoadBalancer(
+            id='234',
+            name='test',
+            state=State.RUNNING,
+            ip='1.2.3.4',
+            port=1234,
+            driver=self.driver,
+            extra=extra
+        )
+        member = Member(
+            id=None,
+            ip='112.12.2.2',
+            port=None,
+            balancer=balancer,
+            extra=None)
+        member = self.driver.balancer_attach_member(balancer, member)
+        self.assertEqual(member.id, '3dd806a2-c2c8-4c0c-9a4f-5219ea9266c0')
+        self.assertEqual(member.port, None)
+
+    def test_balancer_detach_member(self):
+        extra = {'pool_id': '4d360b1f-bc2c-4ab7-9884-1f03ba2768f7',
+                 'network_domain_id': '1234'}
+        balancer = LoadBalancer(
+            id='234',
+            name='test',
+            state=State.RUNNING,
+            ip='1.2.3.4',
+            port=1234,
+            driver=self.driver,
+            extra=extra
+        )
+        member = Member(
+            id='3dd806a2-c2c8-4c0c-9a4f-5219ea9266c0',
+            ip='112.12.2.2',
+            port=80,
+            balancer=balancer,
+            extra=None)
+        result = self.driver.balancer_detach_member(balancer, member)
+        self.assertEqual(result, True)
+
+    def test_destroy_balancer(self):
+        extra = {'pool_id': '4d360b1f-bc2c-4ab7-9884-1f03ba2768f7',
+                 'network_domain_id': '1234'}
+        balancer = LoadBalancer(
+            id='234',
+            name='test',
+            state=State.RUNNING,
+            ip='1.2.3.4',
+            port=1234,
+            driver=self.driver,
+            extra=extra
+        )
+        response = self.driver.destroy_balancer(balancer)
+        self.assertEqual(response, True)
+
+    def test_set_get_network_domain_id(self):
+        self.driver.ex_set_current_network_domain('1234')
+        nwd = self.driver.ex_get_current_network_domain()
+        self.assertEqual(nwd, '1234')
+
+    def test_ex_create_pool_member(self):
+        pool = DimensionDataPool(
+            id='4d360b1f-bc2c-4ab7-9884-1f03ba2768f7',
+            name='test',
+            description='test',
+            status=State.RUNNING,
+            health_monitor_id=None,
+            load_balance_method=None,
+            service_down_action=None,
+            slow_ramp_time=None
+        )
+        node = DimensionDataVIPNode(
+            id='2344',
+            name='test',
+            status=State.RUNNING,
+            ip='123.23.3.2'
+        )
+        member = self.driver.ex_create_pool_member(
+            pool=pool,
+            node=node,
+            port=80
+        )
+        self.assertEqual(member.id, '3dd806a2-c2c8-4c0c-9a4f-5219ea9266c0')
+        self.assertEqual(member.name, '10.0.3.13')
+        self.assertEqual(member.ip, '123.23.3.2')
+
+    def test_ex_create_node(self):
+        node = self.driver.ex_create_node(
+            network_domain_id='12345',
+            name='test',
+            ip='123.12.32.2',
+            ex_description='',
+            connection_limit=25000,
+            connection_rate_limit=2000)
+        self.assertEqual(node.name, 'myProductionNode.1')
+        self.assertEqual(node.id, '9e6b496d-5261-4542-91aa-b50c7f569c54')
+
+    def test_ex_create_pool(self, ):
+        pool = self.driver.ex_create_pool(
+            network_domain_id='1234',
+            name='test',
+            balancer_method='ROUND_ROBIN',
+            ex_description='test',
+            service_down_action='NONE',
+            slow_ramp_time=30)
+        self.assertEqual(pool.id, '9e6b496d-5261-4542-91aa-b50c7f569c54')
+        self.assertEqual(pool.name, 'test')
+        self.assertEqual(pool.status, State.RUNNING)
+
+    def test_ex_create_virtual_listener(self):
+        listener = self.driver.ex_create_virtual_listener(
+            network_domain_id='12345',
+            name='test',
+            ex_description='test',
+            port=80,
+            pool=DimensionDataPool(
+                id='1234',
+                name='test',
+                description='test',
+                status=State.RUNNING,
+                health_monitor_id=None,
+                load_balance_method=None,
+                service_down_action=None,
+                slow_ramp_time=None
+            ))
+        self.assertEqual(listener.id, '8334f461-0df0-42d5-97eb-f4678eb26bea')
+        self.assertEqual(listener.name, 'test')
+
+    def test_ex_create_virtual_listener_unusual_port(self):
+        listener = self.driver.ex_create_virtual_listener(
+            network_domain_id='12345',
+            name='test',
+            ex_description='test',
+            port=8900,
+            pool=DimensionDataPool(
+                id='1234',
+                name='test',
+                description='test',
+                status=State.RUNNING,
+                health_monitor_id=None,
+                load_balance_method=None,
+                service_down_action=None,
+                slow_ramp_time=None
+            ))
+        self.assertEqual(listener.id, '8334f461-0df0-42d5-97eb-f4678eb26bea')
+        self.assertEqual(listener.name, 'test')
+
+    def test_ex_create_virtual_listener_without_port(self):
+        listener = self.driver.ex_create_virtual_listener(
+            network_domain_id='12345',
+            name='test',
+            ex_description='test',
+            pool=DimensionDataPool(
+                id='1234',
+                name='test',
+                description='test',
+                status=State.RUNNING,
+                health_monitor_id=None,
+                load_balance_method=None,
+                service_down_action=None,
+                slow_ramp_time=None
+            ))
+        self.assertEqual(listener.id, '8334f461-0df0-42d5-97eb-f4678eb26bea')
+        self.assertEqual(listener.name, 'test')
+
+    def test_ex_create_virtual_listener_without_pool(self):
+        listener = self.driver.ex_create_virtual_listener(
+            network_domain_id='12345',
+            name='test',
+            ex_description='test')
+        self.assertEqual(listener.id, '8334f461-0df0-42d5-97eb-f4678eb26bea')
+        self.assertEqual(listener.name, 'test')
+
+    def test_get_balancer(self):
+        bal = self.driver.get_balancer('6115469d-a8bb-445b-bb23-d23b5283f2b9')
+        self.assertEqual(bal.name, 'myProduction.Virtual.Listener')
+        self.assertEqual(bal.id, '6115469d-a8bb-445b-bb23-d23b5283f2b9')
+        self.assertEqual(bal.port, '8899')
+        self.assertEqual(bal.ip, '165.180.12.22')
+        self.assertEqual(bal.state, State.RUNNING)
+
+    def test_list_protocols(self):
+        protocols = self.driver.list_protocols()
+        self.assertNotEqual(0, len(protocols))
+
+    def test_ex_get_nodes(self):
+        nodes = self.driver.ex_get_nodes()
+        self.assertEqual(2, len(nodes))
+        self.assertEqual(nodes[0].name, 'ProductionNode.1')
+        self.assertEqual(nodes[0].id, '34de6ed6-46a4-4dae-a753-2f8d3840c6f9')
+        self.assertEqual(nodes[0].ip, '10.10.10.101')
+
+    def test_ex_get_node(self):
+        node = self.driver.ex_get_node('34de6ed6-46a4-4dae-a753-2f8d3840c6f9')
+        self.assertEqual(node.name, 'ProductionNode.2')
+        self.assertEqual(node.id, '34de6ed6-46a4-4dae-a753-2f8d3840c6f9')
+        self.assertEqual(node.ip, '10.10.10.101')
+
+    def test_ex_update_node(self):
+        node = self.driver.ex_get_node('34de6ed6-46a4-4dae-a753-2f8d3840c6f9')
+        node.connection_limit = '100'
+        result = self.driver.ex_update_node(node)
+        self.assertEqual(result.connection_limit, '100')
+
+    def test_ex_destroy_node(self):
+        result = self.driver.ex_destroy_node('34de6ed6-46a4-4dae-a753-2f8d3840c6f9')
+        self.assertTrue(result)
+
+    def test_ex_set_node_state(self):
+        node = self.driver.ex_get_node('34de6ed6-46a4-4dae-a753-2f8d3840c6f9')
+        result = self.driver.ex_set_node_state(node, False)
+        self.assertEqual(result.connection_limit, '10000')
+
+    def test_ex_get_pools(self):
+        pools = self.driver.ex_get_pools()
+        self.assertNotEqual(0, len(pools))
+        self.assertEqual(pools[0].name, 'myDevelopmentPool.1')
+        self.assertEqual(pools[0].id, '4d360b1f-bc2c-4ab7-9884-1f03ba2768f7')
+
+    def test_ex_get_pool(self):
+        pool = self.driver.ex_get_pool('4d360b1f-bc2c-4ab7-9884-1f03ba2768f7')
+        self.assertEqual(pool.name, 'myDevelopmentPool.1')
+        self.assertEqual(pool.id, '4d360b1f-bc2c-4ab7-9884-1f03ba2768f7')
+
+    def test_ex_update_pool(self):
+        pool = self.driver.ex_get_pool('4d360b1f-bc2c-4ab7-9884-1f03ba2768f7')
+        pool.slow_ramp_time = '120'
+        result = self.driver.ex_update_pool(pool)
+        self.assertTrue(result)
+
+    def test_ex_destroy_pool(self):
+        response = self.driver.ex_destroy_pool(
+            pool=DimensionDataPool(
+                id='4d360b1f-bc2c-4ab7-9884-1f03ba2768f7',
+                name='test',
+                description='test',
+                status=State.RUNNING,
+                health_monitor_id=None,
+                load_balance_method=None,
+                service_down_action=None,
+                slow_ramp_time=None))
+        self.assertTrue(response)
+
+    def test_get_pool_members(self):
+        members = self.driver.ex_get_pool_members('4d360b1f-bc2c-4ab7-9884-1f03ba2768f7')
+        self.assertEqual(2, len(members))
+        self.assertEqual(members[0].id, '3dd806a2-c2c8-4c0c-9a4f-5219ea9266c0')
+        self.assertEqual(members[0].name, '10.0.3.13')
+        self.assertEqual(members[0].status, 'NORMAL')
+        self.assertEqual(members[0].ip, '10.0.3.13')
+        self.assertEqual(members[0].port, 9889)
+        self.assertEqual(members[0].node_id, '3c207269-e75e-11e4-811f-005056806999')
+
+    def test_get_pool_member(self):
+        member = self.driver.ex_get_pool_member('3dd806a2-c2c8-4c0c-9a4f-5219ea9266c0')
+        self.assertEqual(member.id, '3dd806a2-c2c8-4c0c-9a4f-5219ea9266c0')
+        self.assertEqual(member.name, '10.0.3.13')
+        self.assertEqual(member.status, 'NORMAL')
+        self.assertEqual(member.ip, '10.0.3.13')
+        self.assertEqual(member.port, 9889)
+
+    def test_set_pool_member_state(self):
+        member = self.driver.ex_get_pool_member('3dd806a2-c2c8-4c0c-9a4f-5219ea9266c0')
+        result = self.driver.ex_set_pool_member_state(member, True)
+        self.assertTrue(result)
+
+    def test_ex_destroy_pool_member(self):
+        response = self.driver.ex_destroy_pool_member(
+            member=DimensionDataPoolMember(
+                id='',
+                name='test',
+                status=State.RUNNING,
+                ip='1.2.3.4',
+                port=80,
+                node_id='3c207269-e75e-11e4-811f-005056806999'),
+            destroy_node=False)
+        self.assertTrue(response)
+
+    def test_ex_destroy_pool_member_with_node(self):
+        response = self.driver.ex_destroy_pool_member(
+            member=DimensionDataPoolMember(
+                id='',
+                name='test',
+                status=State.RUNNING,
+                ip='1.2.3.4',
+                port=80,
+                node_id='34de6ed6-46a4-4dae-a753-2f8d3840c6f9'),
+            destroy_node=True)
+        self.assertTrue(response)
+
+    def test_ex_get_default_health_monitors(self):
+        monitors = self.driver.ex_get_default_health_monitors(
+            '4d360b1f-bc2c-4ab7-9884-1f03ba2768f7'
+        )
+        self.assertEqual(len(monitors), 6)
+        self.assertEqual(monitors[0].id, '01683574-d487-11e4-811f-005056806999')
+        self.assertEqual(monitors[0].name, 'CCDEFAULT.Http')
+        self.assertFalse(monitors[0].node_compatible)
+        self.assertTrue(monitors[0].pool_compatible)
+
+    def test_ex_get_default_persistence_profiles(self):
+        profiles = self.driver.ex_get_default_persistence_profiles(
+            '4d360b1f-bc2c-4ab7-9884-1f03ba2768f7'
+        )
+        self.assertEqual(len(profiles), 4)
+        self.assertEqual(profiles[0].id, 'a34ca024-f3db-11e4-b010-005056806999')
+        self.assertEqual(profiles[0].name, 'CCDEFAULT.Cookie')
+        self.assertEqual(profiles[0].fallback_compatible, False)
+        self.assertEqual(len(profiles[0].compatible_listeners), 1)
+        self.assertEqual(profiles[0].compatible_listeners[0].type, 'PERFORMANCE_LAYER_4')
+
+    def test_ex_get_default_irules(self):
+        irules = self.driver.ex_get_default_irules(
+            '4d360b1f-bc2c-4ab7-9884-1f03ba2768f7'
+        )
+        self.assertEqual(len(irules), 4)
+        self.assertEqual(irules[0].id, '2b20cb2c-ffdc-11e4-b010-005056806999')
+        self.assertEqual(irules[0].name, 'CCDEFAULT.HttpsRedirect')
+        self.assertEqual(len(irules[0].compatible_listeners), 1)
+        self.assertEqual(irules[0].compatible_listeners[0].type, 'PERFORMANCE_LAYER_4')
+
+
+class DimensionDataMockHttp(MockHttp):
+
+    fixtures = LoadBalancerFileFixtures('dimensiondata')
+
+    def _oec_0_9_myaccount_UNAUTHORIZED(self, method, url, body, headers):
+        return (httplib.UNAUTHORIZED, "", {}, httplib.responses[httplib.UNAUTHORIZED])
+
+    def _oec_0_9_myaccount(self, method, url, body, headers):
+        body = self.fixtures.load('oec_0_9_myaccount.xml')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+    def _oec_0_9_myaccount_INPROGRESS(self, method, url, body, headers):
+        body = self.fixtures.load('oec_0_9_myaccount.xml')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_virtualListener(self, method, url, body, headers):
+        body = self.fixtures.load(
+            'networkDomainVip_virtualListener.xml')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_virtualListener_6115469d_a8bb_445b_bb23_d23b5283f2b9(self, method, url, body, headers):
+        body = self.fixtures.load(
+            'networkDomainVip_virtualListener_6115469d_a8bb_445b_bb23_d23b5283f2b9.xml')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_pool(self, method, url, body, headers):
+        body = self.fixtures.load(
+            'networkDomainVip_pool.xml')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_pool_4d360b1f_bc2c_4ab7_9884_1f03ba2768f7(self, method, url, body, headers):
+        body = self.fixtures.load(
+            'networkDomainVip_pool_4d360b1f_bc2c_4ab7_9884_1f03ba2768f7.xml')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_poolMember(self, method, url, body, headers):
+        body = self.fixtures.load(
+            'networkDomainVip_poolMember.xml')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_poolMember_3dd806a2_c2c8_4c0c_9a4f_5219ea9266c0(self, method, url, body, headers):
+        body = self.fixtures.load(
+            'networkDomainVip_poolMember_3dd806a2_c2c8_4c0c_9a4f_5219ea9266c0.xml')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_createPool(self, method, url, body, headers):
+        body = self.fixtures.load(
+            'networkDomainVip_createPool.xml')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_createNode(self, method, url, body, headers):
+        body = self.fixtures.load(
+            'networkDomainVip_createNode.xml')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_addPoolMember(self, method, url, body, headers):
+        body = self.fixtures.load(
+            'networkDomainVip_addPoolMember.xml')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_createVirtualListener(self, method, url, body, headers):
+        body = self.fixtures.load(
+            'networkDomainVip_createVirtualListener.xml')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_removePoolMember(self, method, url, body, headers):
+        body = self.fixtures.load(
+            'networkDomainVip_removePoolMember.xml')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_deleteVirtualListener(self, method, url, body, headers):
+        body = self.fixtures.load(
+            'networkDomainVip_deleteVirtualListener.xml')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_deletePool(self, method, url, body, headers):
+        body = self.fixtures.load(
+            'networkDomainVip_deletePool.xml')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_deleteNode(self, method, url, body, headers):
+        body = self.fixtures.load(
+            'networkDomainVip_deleteNode.xml')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_node(self, method, url, body, headers):
+        body = self.fixtures.load(
+            'networkDomainVip_node.xml')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_node_34de6ed6_46a4_4dae_a753_2f8d3840c6f9(self, method, url, body, headers):
+        body = self.fixtures.load(
+            'networkDomainVip_node_34de6ed6_46a4_4dae_a753_2f8d3840c6f9.xml')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_editNode(self, method, url, body, headers):
+        body = self.fixtures.load(
+            'networkDomainVip_editNode.xml')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_editPool(self, method, url, body, headers):
+        body = self.fixtures.load(
+            'networkDomainVip_editPool.xml')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_editPoolMember(self, method, url, body, headers):
+        body = self.fixtures.load(
+            'networkDomainVip_editPoolMember.xml')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_defaultHealthMonitor(self, method, url, body, headers):
+        body = self.fixtures.load(
+            'networkDomainVip_defaultHealthMonitor.xml')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_defaultPersistenceProfile(self, method, url, body, headers):
+        body = self.fixtures.load(
+            'networkDomainVip_defaultPersistenceProfile.xml')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_defaultIrule(self, method, url, body, headers):
+        body = self.fixtures.load(
+            'networkDomainVip_defaultIrule.xml')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+if __name__ == '__main__':
+    sys.exit(unittest.main())


[08/40] libcloud git commit: Backward compatibility with 2.3

Posted by an...@apache.org.
Backward compatibility with 2.3


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

Branch: refs/heads/trunk
Commit: 9cb7785e1707b7c688820a7a7a6a8a1df9c19597
Parents: 1c2f34a
Author: Samuel Chong <sa...@gmail.com>
Authored: Wed Nov 9 10:26:23 2016 +1100
Committer: Samuel Chong <sa...@gmail.com>
Committed: Wed Nov 9 10:26:23 2016 +1100

----------------------------------------------------------------------
 libcloud/common/dimensiondata.py          |  2 +-
 libcloud/compute/drivers/dimensiondata.py | 18 +++++++++++++++---
 2 files changed, 16 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/libcloud/blob/9cb7785e/libcloud/common/dimensiondata.py
----------------------------------------------------------------------
diff --git a/libcloud/common/dimensiondata.py b/libcloud/common/dimensiondata.py
index ac42871..bf2631e 100644
--- a/libcloud/common/dimensiondata.py
+++ b/libcloud/common/dimensiondata.py
@@ -383,7 +383,7 @@ class DimensionDataConnection(ConnectionUserAndKey):
     oldest_api_version = 2.2
 
     # Latest version supported
-    latest_api_version = 2.3
+    latest_api_version = 2.4
 
     # Default api version
     active_api_version = 2.3

http://git-wip-us.apache.org/repos/asf/libcloud/blob/9cb7785e/libcloud/compute/drivers/dimensiondata.py
----------------------------------------------------------------------
diff --git a/libcloud/compute/drivers/dimensiondata.py b/libcloud/compute/drivers/dimensiondata.py
index c574d09..b0a5959 100644
--- a/libcloud/compute/drivers/dimensiondata.py
+++ b/libcloud/compute/drivers/dimensiondata.py
@@ -787,7 +787,7 @@ class DimensionDataNodeDriver(NodeDriver):
 
         Note:  Currently only returns the default 'base OS images'
                provided by DimensionData. Customer images (snapshots)
-               are not yet supported.
+               use ex_list_customer_images
 
         :keyword ex_location: Filters the node list to nodes that are
                               located in this location
@@ -800,12 +800,20 @@ class DimensionDataNodeDriver(NodeDriver):
         if location is not None:
             params['datacenterId'] = self._location_to_location_id(location)
 
-        return self._to_images(
+        # return self._to_images(
+        #     self.connection.request_with_orgId_api_2(
+        #         'image/osImage',
+        #         params=params)
+        #     .object)
+
+        images = self._to_images(
             self.connection.request_with_orgId_api_2(
                 'image/osImage',
                 params=params)
             .object)
 
+        return images
+
     def list_sizes(self, location=None):
         """
         return a list of available sizes
@@ -3653,7 +3661,11 @@ class DimensionDataNodeDriver(NodeDriver):
                                locations))[0]
 
         cpu_spec = self._to_cpu_spec(element.find(fixxpath('cpu', TYPES_URN)))
-        os_el = element.find(fixxpath('guest/operatingSystem', TYPES_URN))
+
+        if float(self.connection.active_api_version) > 2.3:
+            os_el = element.find(fixxpath('guest/operatingSystem', TYPES_URN))
+        else:
+            os_el = element.find(fixxpath('operatingSystem', TYPES_URN))
 
         if element.tag.endswith('customerImage'):
             is_customer_image = True


[02/40] libcloud git commit: update comment

Posted by an...@apache.org.
update comment


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

Branch: refs/heads/trunk
Commit: 45fea8d5f4b7a8bb3147d79ceebc624f36200491
Parents: f4caab3
Author: Samuel Chong <sa...@gmail.com>
Authored: Thu Nov 3 15:01:57 2016 +1100
Committer: Samuel Chong <sa...@gmail.com>
Committed: Thu Nov 3 15:01:57 2016 +1100

----------------------------------------------------------------------
 libcloud/compute/drivers/dimensiondata.py | 1 -
 1 file changed, 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/libcloud/blob/45fea8d5/libcloud/compute/drivers/dimensiondata.py
----------------------------------------------------------------------
diff --git a/libcloud/compute/drivers/dimensiondata.py b/libcloud/compute/drivers/dimensiondata.py
index 9e477b6..13914e3 100644
--- a/libcloud/compute/drivers/dimensiondata.py
+++ b/libcloud/compute/drivers/dimensiondata.py
@@ -369,7 +369,6 @@ class DimensionDataNodeDriver(NodeDriver):
         >>> #                           ex_primary_nic_network_adapter='E1000',
         >>> #                           ex_is_started=False)
         >>>
-        >>> pprint(node)
 
         :keyword    name:   (required) String with a name for this new node
         :type       name:   ``str``


[07/40] libcloud git commit: Merge branch 'enable_api_version' into ngoc_images

Posted by an...@apache.org.
Merge branch 'enable_api_version' into ngoc_images


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

Branch: refs/heads/trunk
Commit: 1c2f34a081556a2762dc5441671351d54a1d0b43
Parents: a8190ca 3b947b3
Author: Samuel Chong <sa...@gmail.com>
Authored: Tue Nov 8 15:56:13 2016 +1100
Committer: Samuel Chong <sa...@gmail.com>
Committed: Tue Nov 8 15:56:13 2016 +1100

----------------------------------------------------------------------
 libcloud/common/dimensiondata.py          | 39 ++++++++++++++++++++++----
 libcloud/compute/drivers/dimensiondata.py |  2 +-
 2 files changed, 34 insertions(+), 7 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/libcloud/blob/1c2f34a0/libcloud/common/dimensiondata.py
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/libcloud/blob/1c2f34a0/libcloud/compute/drivers/dimensiondata.py
----------------------------------------------------------------------


[04/40] libcloud git commit: Set default api versino to 2.3

Posted by an...@apache.org.
Set default api versino to 2.3


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

Branch: refs/heads/trunk
Commit: a8190ca3c15ff19b65ba0a3966108ec81c6c4f96
Parents: 03a2aa4
Author: Samuel Chong <sa...@gmail.com>
Authored: Tue Nov 8 13:10:11 2016 +1100
Committer: Samuel Chong <sa...@gmail.com>
Committed: Tue Nov 8 13:10:11 2016 +1100

----------------------------------------------------------------------
 libcloud/common/dimensiondata.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/libcloud/blob/a8190ca3/libcloud/common/dimensiondata.py
----------------------------------------------------------------------
diff --git a/libcloud/common/dimensiondata.py b/libcloud/common/dimensiondata.py
index 73443e3..674fd7a 100644
--- a/libcloud/common/dimensiondata.py
+++ b/libcloud/common/dimensiondata.py
@@ -378,7 +378,7 @@ class DimensionDataConnection(ConnectionUserAndKey):
     api_path_version_1 = '/oec'
     api_path_version_2 = '/caas'
     api_version_1 = '0.9'
-    api_version_2 = '2.4'
+    api_version_2 = '2.3'
 
     _orgId = None
     responseCls = DimensionDataResponse


[19/40] libcloud git commit: Unit tests for 2.3

Posted by an...@apache.org.
Unit tests for 2.3


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

Branch: refs/heads/trunk
Commit: bb1b810444ba33c11c1bac52151d00477a500123
Parents: e846f57
Author: Samuel Chong <sa...@gmail.com>
Authored: Wed Nov 16 08:15:09 2016 +1100
Committer: Samuel Chong <sa...@gmail.com>
Committed: Wed Nov 16 08:15:09 2016 +1100

----------------------------------------------------------------------
 libcloud/compute/drivers/dimensiondata.py       |   17 +-
 libcloud/test/backup/test_dimensiondata.py      |  502 ---
 libcloud/test/backup/test_dimensiondata_v2_3.py |  503 +++
 libcloud/test/backup/test_dimensiondata_v2_4.py |  503 +++
 .../dimensiondata/2.4/image_customerImage.xml   |   50 +
 ...age_2ffa36c8_1848_49eb_b4fa_9d908775f68c.xml |   17 +
 ...age_5234e5c7_01de_4411_8b6e_baeb8d91cf5d.xml |   17 +
 .../dimensiondata/2.4/image_osImage.xml         |   34 +
 ...age_6b4fb0c7_a57b_4f58_b59c_9958f94f971a.xml |   11 +
 ...age_c14b1a46_2428_44c1_9c1a_b20e6418d08c.xml |   12 +
 .../dimensiondata/image_customerImage.xml       |   59 -
 ...age_2ffa36c8_1848_49eb_b4fa_9d908775f68c.xml |   21 -
 ...age_5234e5c7_01de_4411_8b6e_baeb8d91cf5d.xml |   21 -
 .../fixtures/dimensiondata/image_osImage.xml    |   43 -
 ...age_6b4fb0c7_a57b_4f58_b59c_9958f94f971a.xml |   14 -
 ...age_c14b1a46_2428_44c1_9c1a_b20e6418d08c.xml |   17 -
 libcloud/test/compute/test_dimensiondata.py     | 3281 -----------------
 .../test/compute/test_dimensiondata_v2_3.py     | 3282 ++++++++++++++++++
 .../test/compute/test_dimensiondata_v2_4.py     | 3282 ++++++++++++++++++
 .../test/loadbalancer/test_dimensiondata.py     |  619 ----
 .../loadbalancer/test_dimensiondata_v2_3.py     |  620 ++++
 .../loadbalancer/test_dimensiondata_v2_4.py     |  620 ++++
 22 files changed, 8962 insertions(+), 4583 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/libcloud/blob/bb1b8104/libcloud/compute/drivers/dimensiondata.py
----------------------------------------------------------------------
diff --git a/libcloud/compute/drivers/dimensiondata.py b/libcloud/compute/drivers/dimensiondata.py
index d869e0a..ab3a0a7 100644
--- a/libcloud/compute/drivers/dimensiondata.py
+++ b/libcloud/compute/drivers/dimensiondata.py
@@ -21,6 +21,7 @@ try:
 except ImportError:
     from xml.etree import ElementTree as ET
 
+from distutils.version import LooseVersion, StrictVersion
 from libcloud.common.exceptions import BaseHTTPError
 from libcloud.compute.base import NodeDriver, Node, NodeAuthPassword
 from libcloud.compute.base import NodeSize, NodeImage, NodeLocation
@@ -2431,7 +2432,8 @@ class DimensionDataNodeDriver(NodeDriver):
         node_id = self._node_to_node_id(node)
 
         # Version 2.3 and lower
-        if float(self.connection.active_api_version) < 2.4:
+        if LooseVersion(self.connection.active_api_version) < LooseVersion(
+                '2.4'):
             response = self.connection.request_with_orgId_api_1(
                 'server/%s?clone=%s&desc=%s' %
                 (node_id, image_name, image_description)).object
@@ -2469,7 +2471,8 @@ class DimensionDataNodeDriver(NodeDriver):
                 data=ET.tostring(clone_server_elem)).object
 
         # Version 2.3 and lower
-        if float(self.connection.active_api_version) < 2.4:
+        if LooseVersion(self.connection.active_api_version) < LooseVersion(
+                '2.4'):
             response_code = findtext(response, 'result', GENERAL_NS)
         else:
             response_code = findtext(response, 'responseCode', TYPES_URN)
@@ -3628,7 +3631,8 @@ class DimensionDataNodeDriver(NodeDriver):
                      is_guest_os_customization=None,
                      tagkey_name_value_dictionaries=None):
         # Unsupported for version lower than 2.4
-        if float(self.connection.active_api_version) < 2.4:
+        if LooseVersion(self.connection.active_api_version) < LooseVersion(
+                '2.4'):
             raise Exception("import image is feature is NOT supported in  " \
                             "api version earlier than 2.4")
         else:
@@ -3686,7 +3690,6 @@ class DimensionDataNodeDriver(NodeDriver):
         response_code = findtext(response, 'responseCode', TYPES_URN)
         return response_code in ['IN_PROGRESS', 'OK']
 
-
     def _format_csv(self, http_response):
         text = http_response.read()
         lines = str.splitlines(ensure_string(text))
@@ -3764,7 +3767,8 @@ class DimensionDataNodeDriver(NodeDriver):
 
         cpu_spec = self._to_cpu_spec(element.find(fixxpath('cpu', TYPES_URN)))
 
-        if float(self.connection.active_api_version) > 2.3:
+        if LooseVersion(self.connection.active_api_version) > LooseVersion(
+                '2.3'):
             os_el = element.find(fixxpath('guest/operatingSystem', TYPES_URN))
         else:
             os_el = element.find(fixxpath('operatingSystem', TYPES_URN))
@@ -4052,7 +4056,8 @@ class DimensionDataNodeDriver(NodeDriver):
         disks = self._to_disks(element)
 
         # Version 2.3 or earlier
-        if float(self.connection.active_api_version) < 2.4:
+        if LooseVersion(self.connection.active_api_version) < LooseVersion(
+                '2.4'):
             vmware_tools = self._to_vmware_tools(
                 element.find(fixxpath('vmwareTools', TYPES_URN)))
             operation_system = element.find(fixxpath(

http://git-wip-us.apache.org/repos/asf/libcloud/blob/bb1b8104/libcloud/test/backup/test_dimensiondata.py
----------------------------------------------------------------------
diff --git a/libcloud/test/backup/test_dimensiondata.py b/libcloud/test/backup/test_dimensiondata.py
deleted file mode 100644
index 3214cff..0000000
--- a/libcloud/test/backup/test_dimensiondata.py
+++ /dev/null
@@ -1,502 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License.  You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-try:
-    from lxml import etree as ET
-except ImportError:
-    from xml.etree import ElementTree as ET
-
-import sys
-from libcloud.utils.py3 import httplib
-
-from libcloud.common.dimensiondata import DimensionDataAPIException
-from libcloud.common.types import InvalidCredsError
-from libcloud.backup.base import BackupTargetJob
-from libcloud.backup.drivers.dimensiondata import DimensionDataBackupDriver as DimensionData
-from libcloud.backup.drivers.dimensiondata import DEFAULT_BACKUP_PLAN
-
-from libcloud.test import MockHttp, unittest
-from libcloud.test.backup import TestCaseMixin
-from libcloud.test.file_fixtures import BackupFileFixtures
-
-from libcloud.test.secrets import DIMENSIONDATA_PARAMS
-
-
-class DimensionDataTests(unittest.TestCase, TestCaseMixin):
-
-    def setUp(self):
-        DimensionData.connectionCls.conn_classes = (None, DimensionDataMockHttp)
-        DimensionDataMockHttp.type = None
-        self.driver = DimensionData(*DIMENSIONDATA_PARAMS)
-
-    def test_invalid_region(self):
-        with self.assertRaises(ValueError):
-            self.driver = DimensionData(*DIMENSIONDATA_PARAMS, region='blah')
-
-    def test_invalid_creds(self):
-        DimensionDataMockHttp.type = 'UNAUTHORIZED'
-        with self.assertRaises(InvalidCredsError):
-            self.driver.list_targets()
-
-    def test_list_targets(self):
-        targets = self.driver.list_targets()
-        self.assertEqual(len(targets), 2)
-        self.assertEqual(targets[0].id, '5579f3a7-4c32-4cf5-8a7e-b45c36a35c10')
-        self.assertEqual(targets[0].address, 'e75ead52-692f-4314-8725-c8a4f4d13a87')
-        self.assertEqual(targets[0].extra['servicePlan'], 'Enterprise')
-
-    def test_create_target(self):
-        target = self.driver.create_target(
-            'name',
-            'e75ead52-692f-4314-8725-c8a4f4d13a87',
-            extra={'servicePlan': 'Enterprise'})
-        self.assertEqual(target.id, 'ee7c4b64-f7af-4a4f-8384-be362273530f')
-        self.assertEqual(target.address, 'e75ead52-692f-4314-8725-c8a4f4d13a87')
-        self.assertEqual(target.extra['servicePlan'], 'Enterprise')
-
-    def test_create_target_DEFAULT(self):
-        DimensionDataMockHttp.type = 'DEFAULT'
-        target = self.driver.create_target(
-            'name',
-            'e75ead52-692f-4314-8725-c8a4f4d13a87')
-        self.assertEqual(target.id, 'ee7c4b64-f7af-4a4f-8384-be362273530f')
-        self.assertEqual(target.address, 'e75ead52-692f-4314-8725-c8a4f4d13a87')
-
-    def test_create_target_EXISTS(self):
-        DimensionDataMockHttp.type = 'EXISTS'
-        with self.assertRaises(DimensionDataAPIException) as context:
-            self.driver.create_target(
-                'name',
-                'e75ead52-692f-4314-8725-c8a4f4d13a87',
-                extra={'servicePlan': 'Enterprise'})
-        self.assertEqual(context.exception.code, 'ERROR')
-        self.assertEqual(context.exception.msg, 'Cloud backup for this server is already enabled or being enabled (state: NORMAL).')
-
-    def test_update_target(self):
-        target = self.driver.list_targets()[0]
-        extra = {'servicePlan': 'Essentials'}
-        new_target = self.driver.update_target(target, extra=extra)
-        self.assertEqual(new_target.extra['servicePlan'], 'Essentials')
-
-    def test_update_target_DEFAULT(self):
-        DimensionDataMockHttp.type = 'DEFAULT'
-        target = 'e75ead52-692f-4314-8725-c8a4f4d13a87'
-        self.driver.update_target(target)
-
-    def test_update_target_STR(self):
-        target = 'e75ead52-692f-4314-8725-c8a4f4d13a87'
-        extra = {'servicePlan': 'Essentials'}
-        new_target = self.driver.update_target(target, extra=extra)
-        self.assertEqual(new_target.extra['servicePlan'], 'Essentials')
-
-    def test_delete_target(self):
-        target = self.driver.list_targets()[0]
-        self.assertTrue(self.driver.delete_target(target))
-
-    def test_ex_add_client_to_target(self):
-        target = self.driver.list_targets()[0]
-        client = self.driver.ex_list_available_client_types(target)[0]
-        storage_policy = self.driver.ex_list_available_storage_policies(target)[0]
-        schedule_policy = self.driver.ex_list_available_schedule_policies(target)[0]
-        self.assertTrue(
-            self.driver.ex_add_client_to_target(target, client, storage_policy,
-                                                schedule_policy, 'ON_FAILURE', 'nobody@example.com')
-        )
-
-    def test_ex_add_client_to_target_STR(self):
-        self.assertTrue(
-            self.driver.ex_add_client_to_target('e75ead52-692f-4314-8725-c8a4f4d13a87', 'FA.Linux', '14 Day Storage Policy',
-                                                '12AM - 6AM', 'ON_FAILURE', 'nobody@example.com')
-        )
-
-    def test_ex_get_backup_details_for_target(self):
-        target = self.driver.list_targets()[0]
-        response = self.driver.ex_get_backup_details_for_target(target)
-        self.assertEqual(response.service_plan, 'Enterprise')
-        client = response.clients[0]
-        self.assertEqual(client.id, '30b1ff76-c76d-4d7c-b39d-3b72be0384c8')
-        self.assertEqual(client.type.type, 'FA.Linux')
-        self.assertEqual(client.running_job.progress, 5)
-        self.assertTrue(isinstance(client.running_job, BackupTargetJob))
-        self.assertEqual(len(client.alert.notify_list), 2)
-        self.assertTrue(isinstance(client.alert.notify_list, list))
-
-    def test_ex_get_backup_details_for_target_NOBACKUP(self):
-        target = self.driver.list_targets()[0].address
-        DimensionDataMockHttp.type = 'NOBACKUP'
-        response = self.driver.ex_get_backup_details_for_target(target)
-        self.assertTrue(response is None)
-
-    def test_ex_cancel_target_job(self):
-        target = self.driver.list_targets()[0]
-        response = self.driver.ex_get_backup_details_for_target(target)
-        client = response.clients[0]
-        self.assertTrue(isinstance(client.running_job, BackupTargetJob))
-        success = client.running_job.cancel()
-        self.assertTrue(success)
-
-    def test_ex_cancel_target_job_with_extras(self):
-        success = self.driver.cancel_target_job(
-            None,
-            ex_client='30b1ff76_c76d_4d7c_b39d_3b72be0384c8',
-            ex_target='e75ead52_692f_4314_8725_c8a4f4d13a87'
-        )
-        self.assertTrue(success)
-
-    def test_ex_cancel_target_job_FAIL(self):
-        DimensionDataMockHttp.type = 'FAIL'
-        with self.assertRaises(DimensionDataAPIException) as context:
-            self.driver.cancel_target_job(
-                None,
-                ex_client='30b1ff76_c76d_4d7c_b39d_3b72be0384c8',
-                ex_target='e75ead52_692f_4314_8725_c8a4f4d13a87'
-            )
-        self.assertEqual(context.exception.code, 'ERROR')
-
-    """Test a backup info for a target that does not have a client"""
-    def test_ex_get_backup_details_for_target_NO_CLIENT(self):
-        DimensionDataMockHttp.type = 'NOCLIENT'
-        response = self.driver.ex_get_backup_details_for_target('e75ead52-692f-4314-8725-c8a4f4d13a87')
-        self.assertEqual(response.service_plan, 'Essentials')
-        self.assertEqual(len(response.clients), 0)
-
-    """Test a backup details that has a client, but no alerting or running jobs"""
-    def test_ex_get_backup_details_for_target_NO_JOB_OR_ALERT(self):
-        DimensionDataMockHttp.type = 'NOJOB'
-        response = self.driver.ex_get_backup_details_for_target('e75ead52-692f-4314_8725-c8a4f4d13a87')
-        self.assertEqual(response.service_plan, 'Enterprise')
-        self.assertTrue(isinstance(response.clients, list))
-        self.assertEqual(len(response.clients), 1)
-        client = response.clients[0]
-        self.assertEqual(client.id, '30b1ff76-c76d-4d7c-b39d-3b72be0384c8')
-        self.assertEqual(client.type.type, 'FA.Linux')
-        self.assertIsNone(client.running_job)
-        self.assertIsNone(client.alert)
-
-    """Test getting backup info for a server that doesn't exist"""
-    def test_ex_get_backup_details_for_target_DISABLED(self):
-        DimensionDataMockHttp.type = 'DISABLED'
-        with self.assertRaises(DimensionDataAPIException) as context:
-            self.driver.ex_get_backup_details_for_target('e75ead52-692f-4314-8725-c8a4f4d13a87')
-        self.assertEqual(context.exception.code, 'ERROR')
-        self.assertEqual(context.exception.msg, 'Server e75ead52-692f-4314-8725-c8a4f4d13a87 has not been provisioned for backup')
-
-    def test_ex_list_available_client_types(self):
-        target = self.driver.list_targets()[0]
-        answer = self.driver.ex_list_available_client_types(target)
-        self.assertEqual(len(answer), 1)
-        self.assertEqual(answer[0].type, 'FA.Linux')
-        self.assertEqual(answer[0].is_file_system, True)
-        self.assertEqual(answer[0].description, 'Linux File system')
-
-    def test_ex_list_available_storage_policies(self):
-        target = self.driver.list_targets()[0]
-        answer = self.driver.ex_list_available_storage_policies(target)
-        self.assertEqual(len(answer), 1)
-        self.assertEqual(answer[0].name,
-                         '30 Day Storage Policy + Secondary Copy')
-        self.assertEqual(answer[0].retention_period, 30)
-        self.assertEqual(answer[0].secondary_location, 'Primary')
-
-    def test_ex_list_available_schedule_policies(self):
-        target = self.driver.list_targets()[0]
-        answer = self.driver.ex_list_available_schedule_policies(target)
-        self.assertEqual(len(answer), 1)
-        self.assertEqual(answer[0].name, '12AM - 6AM')
-        self.assertEqual(answer[0].description, 'Daily backup will start between 12AM - 6AM')
-
-    def test_ex_remove_client_from_target(self):
-        target = self.driver.list_targets()[0]
-        client = self.driver.ex_get_backup_details_for_target('e75ead52-692f-4314-8725-c8a4f4d13a87').clients[0]
-        self.assertTrue(self.driver.ex_remove_client_from_target(target, client))
-
-    def test_ex_remove_client_from_target_STR(self):
-        self.assertTrue(
-            self.driver.ex_remove_client_from_target(
-                'e75ead52-692f-4314-8725-c8a4f4d13a87',
-                '30b1ff76-c76d-4d7c-b39d-3b72be0384c8'
-            )
-        )
-
-    def test_ex_remove_client_from_target_FAIL(self):
-        DimensionDataMockHttp.type = 'FAIL'
-        with self.assertRaises(DimensionDataAPIException) as context:
-            self.driver.ex_remove_client_from_target(
-                'e75ead52-692f-4314-8725-c8a4f4d13a87',
-                '30b1ff76-c76d-4d7c-b39d-3b72be0384c8'
-            )
-        self.assertEqual(context.exception.code, 'ERROR')
-        self.assertTrue('Backup Client is currently performing another operation' in context.exception.msg)
-
-    def test_priv_target_to_target_address(self):
-        target = self.driver.list_targets()[0]
-        self.assertEqual(
-            self.driver._target_to_target_address(target),
-            'e75ead52-692f-4314-8725-c8a4f4d13a87'
-        )
-
-    def test_priv_target_to_target_address_STR(self):
-        self.assertEqual(
-            self.driver._target_to_target_address('e75ead52-692f-4314-8725-c8a4f4d13a87'),
-            'e75ead52-692f-4314-8725-c8a4f4d13a87'
-        )
-
-    def test_priv_target_to_target_address_TYPEERROR(self):
-        with self.assertRaises(TypeError):
-            self.driver._target_to_target_address([1, 2, 3])
-
-    def test_priv_client_to_client_id(self):
-        client = self.driver.ex_get_backup_details_for_target('e75ead52-692f-4314-8725-c8a4f4d13a87').clients[0]
-        self.assertEqual(
-            self.driver._client_to_client_id(client),
-            '30b1ff76-c76d-4d7c-b39d-3b72be0384c8'
-        )
-
-    def test_priv_client_to_client_id_STR(self):
-        self.assertEqual(
-            self.driver._client_to_client_id('30b1ff76-c76d-4d7c-b39d-3b72be0384c8'),
-            '30b1ff76-c76d-4d7c-b39d-3b72be0384c8'
-        )
-
-    def test_priv_client_to_client_id_TYPEERROR(self):
-        with self.assertRaises(TypeError):
-            self.driver._client_to_client_id([1, 2, 3])
-
-
-class InvalidRequestError(Exception):
-    def __init__(self, tag):
-        super(InvalidRequestError, self).__init__("Invalid Request - %s" % tag)
-
-
-class DimensionDataMockHttp(MockHttp):
-
-    fixtures = BackupFileFixtures('dimensiondata')
-
-    def _oec_0_9_myaccount_UNAUTHORIZED(self, method, url, body, headers):
-        return (httplib.UNAUTHORIZED, "", {}, httplib.responses[httplib.UNAUTHORIZED])
-
-    def _oec_0_9_myaccount(self, method, url, body, headers):
-        body = self.fixtures.load('oec_0_9_myaccount.xml')
-        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
-
-    def _oec_0_9_myaccount_EXISTS(self, method, url, body, headers):
-        body = self.fixtures.load('oec_0_9_myaccount.xml')
-        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
-
-    def _oec_0_9_myaccount_DEFAULT(self, method, url, body, headers):
-        body = self.fixtures.load('oec_0_9_myaccount.xml')
-        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
-
-    def _oec_0_9_myaccount_INPROGRESS(self, method, url, body, headers):
-        body = self.fixtures.load('oec_0_9_myaccount.xml')
-        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
-
-    def _oec_0_9_myaccount_FAIL(self, method, url, body, headers):
-        body = self.fixtures.load('oec_0_9_myaccount.xml')
-        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
-
-    def _oec_0_9_myaccount_NOCLIENT(self, method, url, body, headers):
-        body = self.fixtures.load('oec_0_9_myaccount.xml')
-        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
-
-    def _oec_0_9_myaccount_DISABLED(self, method, url, body, headers):
-        body = self.fixtures.load('oec_0_9_myaccount.xml')
-        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
-
-    def _oec_0_9_myaccount_NOJOB(self, method, url, body, headers):
-        body = self.fixtures.load('oec_0_9_myaccount.xml')
-        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
-
-    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_server_e75ead52_692f_4314_8725_c8a4f4d13a87(self, method, url, body, headers):
-        body = self.fixtures.load(
-            'server_server_e75ead52_692f_4314_8725_c8a4f4d13a87.xml')
-        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
-
-    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_server_e75ead52_692f_4314_8725_c8a4f4d13a87_DEFAULT(self, method, url, body, headers):
-        body = self.fixtures.load(
-            'server_server_e75ead52_692f_4314_8725_c8a4f4d13a87_DEFAULT.xml')
-        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
-
-    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_server_e75ead52_692f_4314_8725_c8a4f4d13a87_NOCLIENT(self, method, url, body, headers):
-        body = self.fixtures.load(
-            'server_server_e75ead52_692f_4314_8725_c8a4f4d13a87_DEFAULT.xml')
-        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
-
-    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_server_e75ead52_692f_4314_8725_c8a4f4d13a87_NOJOB(self, method, url, body, headers):
-        body = self.fixtures.load(
-            'server_server_e75ead52_692f_4314_8725_c8a4f4d13a87_DEFAULT.xml')
-        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
-
-    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_server_e75ead52_692f_4314_8725_c8a4f4d13a87_DISABLED(self, method, url, body, headers):
-        body = self.fixtures.load(
-            'server_server_e75ead52_692f_4314_8725_c8a4f4d13a87_DEFAULT.xml')
-        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
-
-    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_server(self, method, url, body, headers):
-        body = self.fixtures.load(
-            'server_server.xml')
-        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
-
-    def _oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_e75ead52_692f_4314_8725_c8a4f4d13a87_backup_client_type(self, method, url, body, headers):
-        body = self.fixtures.load(
-            '_backup_client_type.xml')
-        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
-
-    def _oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_e75ead52_692f_4314_8725_c8a4f4d13a87_backup_client_storagePolicy(
-            self, method, url, body, headers):
-        body = self.fixtures.load(
-            '_backup_client_storagePolicy.xml')
-        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
-
-    def _oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_e75ead52_692f_4314_8725_c8a4f4d13a87_backup_client_schedulePolicy(
-            self, method, url, body, headers):
-        body = self.fixtures.load(
-            '_backup_client_schedulePolicy.xml')
-        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
-
-    def _oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_e75ead52_692f_4314_8725_c8a4f4d13a87_backup_client(
-            self, method, url, body, headers):
-        if method == 'POST':
-            body = self.fixtures.load(
-                '_backup_client_SUCCESS_PUT.xml')
-            return (httplib.OK, body, {}, httplib.responses[httplib.OK])
-        else:
-            raise ValueError("Unknown Method {0}".format(method))
-
-    def _oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_e75ead52_692f_4314_8725_c8a4f4d13a87_backup_NOCLIENT(
-            self, method, url, body, headers):
-        # only gets here are implemented
-        # If we get any other method something has gone wrong
-        assert(method == 'GET')
-        body = self.fixtures.load(
-            '_backup_INFO_NOCLIENT.xml')
-        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
-
-    def _oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_e75ead52_692f_4314_8725_c8a4f4d13a87_backup_DISABLED(
-            self, method, url, body, headers):
-        # only gets here are implemented
-        # If we get any other method something has gone wrong
-        assert(method == 'GET')
-        body = self.fixtures.load(
-            '_backup_INFO_DISABLED.xml')
-        return (httplib.BAD_REQUEST, body, {}, httplib.responses[httplib.OK])
-
-    def _oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_e75ead52_692f_4314_8725_c8a4f4d13a87_backup_NOJOB(
-            self, method, url, body, headers):
-        # only gets here are implemented
-        # If we get any other method something has gone wrong
-        assert(method == 'GET')
-        body = self.fixtures.load(
-            '_backup_INFO_NOJOB.xml')
-        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
-
-    def _oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_e75ead52_692f_4314_8725_c8a4f4d13a87_backup_DEFAULT(
-            self, method, url, body, headers):
-        if method != 'POST':
-            raise InvalidRequestError('Only POST is accepted for this test')
-        request = ET.fromstring(body)
-        service_plan = request.get('servicePlan')
-        if service_plan != DEFAULT_BACKUP_PLAN:
-            raise InvalidRequestError('The default plan %s should have been passed in.  Not %s' % (DEFAULT_BACKUP_PLAN, service_plan))
-        body = self.fixtures.load(
-            '_backup_ENABLE.xml')
-        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
-
-    def _oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_e75ead52_692f_4314_8725_c8a4f4d13a87_backup(
-            self, method, url, body, headers):
-        if method == 'POST':
-            body = self.fixtures.load(
-                '_backup_ENABLE.xml')
-            return (httplib.OK, body, {}, httplib.responses[httplib.OK])
-        elif method == 'GET':
-            if url.endswith('disable'):
-                body = self.fixtures.load(
-                    '_backup_DISABLE.xml')
-                return (httplib.OK, body, {}, httplib.responses[httplib.OK])
-            body = self.fixtures.load(
-                '_backup_INFO.xml')
-            return (httplib.OK, body, {}, httplib.responses[httplib.OK])
-
-        else:
-            raise ValueError("Unknown Method {0}".format(method))
-
-    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_server_e75ead52_692f_4314_8725_c8a4f4d13a87_NOBACKUP(
-            self, method, url, body, headers):
-        assert(method == 'GET')
-        body = self.fixtures.load('server_server_NOBACKUP.xml')
-        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
-
-    def _oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_e75ead52_692f_4314_8725_c8a4f4d13a87_backup_EXISTS(
-            self, method, url, body, headers):
-        # only POSTs are implemented
-        # If we get any other method something has gone wrong
-        assert(method == 'POST')
-        body = self.fixtures.load(
-            '_backup_EXISTS.xml')
-        return (httplib.BAD_REQUEST, body, {}, httplib.responses[httplib.OK])
-
-    def _oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_e75ead52_692f_4314_8725_c8a4f4d13a87_backup_modify(
-            self, method, url, body, headers):
-        request = ET.fromstring(body)
-        service_plan = request.get('servicePlan')
-        if service_plan != 'Essentials':
-            raise InvalidRequestError("Expected Essentials backup plan in request")
-        body = self.fixtures.load('_backup_modify.xml')
-
-        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
-
-    def _oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_e75ead52_692f_4314_8725_c8a4f4d13a87_backup_modify_DEFAULT(
-            self, method, url, body, headers):
-        request = ET.fromstring(body)
-        service_plan = request.get('servicePlan')
-        if service_plan != DEFAULT_BACKUP_PLAN:
-            raise InvalidRequestError("Expected % backup plan in test" % DEFAULT_BACKUP_PLAN)
-        body = self.fixtures.load('_backup_modify.xml')
-
-        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
-
-    def _oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_e75ead52_692f_4314_8725_c8a4f4d13a87_backup_client_30b1ff76_c76d_4d7c_b39d_3b72be0384c8(
-            self, method, url, body, headers):
-        if url.endswith('disable'):
-            body = self.fixtures.load(
-                ('_remove_backup_client.xml')
-            )
-        elif url.endswith('cancelJob'):
-            body = self.fixtures.load(
-                (''
-                 '_backup_client_30b1ff76_c76d_4d7c_b39d_3b72be0384c8_cancelJob.xml')
-            )
-        else:
-            raise ValueError("Unknown URL: %s" % url)
-        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
-
-    def _oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_e75ead52_692f_4314_8725_c8a4f4d13a87_backup_client_30b1ff76_c76d_4d7c_b39d_3b72be0384c8_FAIL(
-            self, method, url, body, headers):
-        if url.endswith('disable'):
-            body = self.fixtures.load(
-                ('_remove_backup_client_FAIL.xml')
-            )
-        elif url.endswith('cancelJob'):
-            body = self.fixtures.load(
-                (''
-                 '_backup_client_30b1ff76_c76d_4d7c_b39d_3b72be0384c8_cancelJob_FAIL.xml')
-            )
-        else:
-            raise ValueError("Unknown URL: %s" % url)
-        return (httplib.BAD_REQUEST, body, {}, httplib.responses[httplib.OK])
-
-
-if __name__ == '__main__':
-    sys.exit(unittest.main())

http://git-wip-us.apache.org/repos/asf/libcloud/blob/bb1b8104/libcloud/test/backup/test_dimensiondata_v2_3.py
----------------------------------------------------------------------
diff --git a/libcloud/test/backup/test_dimensiondata_v2_3.py b/libcloud/test/backup/test_dimensiondata_v2_3.py
new file mode 100644
index 0000000..ae05316
--- /dev/null
+++ b/libcloud/test/backup/test_dimensiondata_v2_3.py
@@ -0,0 +1,503 @@
+# 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.
+
+try:
+    from lxml import etree as ET
+except ImportError:
+    from xml.etree import ElementTree as ET
+
+import sys
+from libcloud.utils.py3 import httplib
+
+from libcloud.common.dimensiondata import DimensionDataAPIException
+from libcloud.common.types import InvalidCredsError
+from libcloud.backup.base import BackupTargetJob
+from libcloud.backup.drivers.dimensiondata import DimensionDataBackupDriver as DimensionData
+from libcloud.backup.drivers.dimensiondata import DEFAULT_BACKUP_PLAN
+
+from libcloud.test import MockHttp, unittest
+from libcloud.test.backup import TestCaseMixin
+from libcloud.test.file_fixtures import BackupFileFixtures
+
+from libcloud.test.secrets import DIMENSIONDATA_PARAMS
+
+
+class DimensionDataTests(unittest.TestCase, TestCaseMixin):
+
+    def setUp(self):
+        DimensionData.connectionCls.active_api_version = '2.3'
+        DimensionData.connectionCls.conn_classes = (None, DimensionDataMockHttp)
+        DimensionDataMockHttp.type = None
+        self.driver = DimensionData(*DIMENSIONDATA_PARAMS)
+
+    def test_invalid_region(self):
+        with self.assertRaises(ValueError):
+            self.driver = DimensionData(*DIMENSIONDATA_PARAMS, region='blah')
+
+    def test_invalid_creds(self):
+        DimensionDataMockHttp.type = 'UNAUTHORIZED'
+        with self.assertRaises(InvalidCredsError):
+            self.driver.list_targets()
+
+    def test_list_targets(self):
+        targets = self.driver.list_targets()
+        self.assertEqual(len(targets), 2)
+        self.assertEqual(targets[0].id, '5579f3a7-4c32-4cf5-8a7e-b45c36a35c10')
+        self.assertEqual(targets[0].address, 'e75ead52-692f-4314-8725-c8a4f4d13a87')
+        self.assertEqual(targets[0].extra['servicePlan'], 'Enterprise')
+
+    def test_create_target(self):
+        target = self.driver.create_target(
+            'name',
+            'e75ead52-692f-4314-8725-c8a4f4d13a87',
+            extra={'servicePlan': 'Enterprise'})
+        self.assertEqual(target.id, 'ee7c4b64-f7af-4a4f-8384-be362273530f')
+        self.assertEqual(target.address, 'e75ead52-692f-4314-8725-c8a4f4d13a87')
+        self.assertEqual(target.extra['servicePlan'], 'Enterprise')
+
+    def test_create_target_DEFAULT(self):
+        DimensionDataMockHttp.type = 'DEFAULT'
+        target = self.driver.create_target(
+            'name',
+            'e75ead52-692f-4314-8725-c8a4f4d13a87')
+        self.assertEqual(target.id, 'ee7c4b64-f7af-4a4f-8384-be362273530f')
+        self.assertEqual(target.address, 'e75ead52-692f-4314-8725-c8a4f4d13a87')
+
+    def test_create_target_EXISTS(self):
+        DimensionDataMockHttp.type = 'EXISTS'
+        with self.assertRaises(DimensionDataAPIException) as context:
+            self.driver.create_target(
+                'name',
+                'e75ead52-692f-4314-8725-c8a4f4d13a87',
+                extra={'servicePlan': 'Enterprise'})
+        self.assertEqual(context.exception.code, 'ERROR')
+        self.assertEqual(context.exception.msg, 'Cloud backup for this server is already enabled or being enabled (state: NORMAL).')
+
+    def test_update_target(self):
+        target = self.driver.list_targets()[0]
+        extra = {'servicePlan': 'Essentials'}
+        new_target = self.driver.update_target(target, extra=extra)
+        self.assertEqual(new_target.extra['servicePlan'], 'Essentials')
+
+    def test_update_target_DEFAULT(self):
+        DimensionDataMockHttp.type = 'DEFAULT'
+        target = 'e75ead52-692f-4314-8725-c8a4f4d13a87'
+        self.driver.update_target(target)
+
+    def test_update_target_STR(self):
+        target = 'e75ead52-692f-4314-8725-c8a4f4d13a87'
+        extra = {'servicePlan': 'Essentials'}
+        new_target = self.driver.update_target(target, extra=extra)
+        self.assertEqual(new_target.extra['servicePlan'], 'Essentials')
+
+    def test_delete_target(self):
+        target = self.driver.list_targets()[0]
+        self.assertTrue(self.driver.delete_target(target))
+
+    def test_ex_add_client_to_target(self):
+        target = self.driver.list_targets()[0]
+        client = self.driver.ex_list_available_client_types(target)[0]
+        storage_policy = self.driver.ex_list_available_storage_policies(target)[0]
+        schedule_policy = self.driver.ex_list_available_schedule_policies(target)[0]
+        self.assertTrue(
+            self.driver.ex_add_client_to_target(target, client, storage_policy,
+                                                schedule_policy, 'ON_FAILURE', 'nobody@example.com')
+        )
+
+    def test_ex_add_client_to_target_STR(self):
+        self.assertTrue(
+            self.driver.ex_add_client_to_target('e75ead52-692f-4314-8725-c8a4f4d13a87', 'FA.Linux', '14 Day Storage Policy',
+                                                '12AM - 6AM', 'ON_FAILURE', 'nobody@example.com')
+        )
+
+    def test_ex_get_backup_details_for_target(self):
+        target = self.driver.list_targets()[0]
+        response = self.driver.ex_get_backup_details_for_target(target)
+        self.assertEqual(response.service_plan, 'Enterprise')
+        client = response.clients[0]
+        self.assertEqual(client.id, '30b1ff76-c76d-4d7c-b39d-3b72be0384c8')
+        self.assertEqual(client.type.type, 'FA.Linux')
+        self.assertEqual(client.running_job.progress, 5)
+        self.assertTrue(isinstance(client.running_job, BackupTargetJob))
+        self.assertEqual(len(client.alert.notify_list), 2)
+        self.assertTrue(isinstance(client.alert.notify_list, list))
+
+    def test_ex_get_backup_details_for_target_NOBACKUP(self):
+        target = self.driver.list_targets()[0].address
+        DimensionDataMockHttp.type = 'NOBACKUP'
+        response = self.driver.ex_get_backup_details_for_target(target)
+        self.assertTrue(response is None)
+
+    def test_ex_cancel_target_job(self):
+        target = self.driver.list_targets()[0]
+        response = self.driver.ex_get_backup_details_for_target(target)
+        client = response.clients[0]
+        self.assertTrue(isinstance(client.running_job, BackupTargetJob))
+        success = client.running_job.cancel()
+        self.assertTrue(success)
+
+    def test_ex_cancel_target_job_with_extras(self):
+        success = self.driver.cancel_target_job(
+            None,
+            ex_client='30b1ff76_c76d_4d7c_b39d_3b72be0384c8',
+            ex_target='e75ead52_692f_4314_8725_c8a4f4d13a87'
+        )
+        self.assertTrue(success)
+
+    def test_ex_cancel_target_job_FAIL(self):
+        DimensionDataMockHttp.type = 'FAIL'
+        with self.assertRaises(DimensionDataAPIException) as context:
+            self.driver.cancel_target_job(
+                None,
+                ex_client='30b1ff76_c76d_4d7c_b39d_3b72be0384c8',
+                ex_target='e75ead52_692f_4314_8725_c8a4f4d13a87'
+            )
+        self.assertEqual(context.exception.code, 'ERROR')
+
+    """Test a backup info for a target that does not have a client"""
+    def test_ex_get_backup_details_for_target_NO_CLIENT(self):
+        DimensionDataMockHttp.type = 'NOCLIENT'
+        response = self.driver.ex_get_backup_details_for_target('e75ead52-692f-4314-8725-c8a4f4d13a87')
+        self.assertEqual(response.service_plan, 'Essentials')
+        self.assertEqual(len(response.clients), 0)
+
+    """Test a backup details that has a client, but no alerting or running jobs"""
+    def test_ex_get_backup_details_for_target_NO_JOB_OR_ALERT(self):
+        DimensionDataMockHttp.type = 'NOJOB'
+        response = self.driver.ex_get_backup_details_for_target('e75ead52-692f-4314_8725-c8a4f4d13a87')
+        self.assertEqual(response.service_plan, 'Enterprise')
+        self.assertTrue(isinstance(response.clients, list))
+        self.assertEqual(len(response.clients), 1)
+        client = response.clients[0]
+        self.assertEqual(client.id, '30b1ff76-c76d-4d7c-b39d-3b72be0384c8')
+        self.assertEqual(client.type.type, 'FA.Linux')
+        self.assertIsNone(client.running_job)
+        self.assertIsNone(client.alert)
+
+    """Test getting backup info for a server that doesn't exist"""
+    def test_ex_get_backup_details_for_target_DISABLED(self):
+        DimensionDataMockHttp.type = 'DISABLED'
+        with self.assertRaises(DimensionDataAPIException) as context:
+            self.driver.ex_get_backup_details_for_target('e75ead52-692f-4314-8725-c8a4f4d13a87')
+        self.assertEqual(context.exception.code, 'ERROR')
+        self.assertEqual(context.exception.msg, 'Server e75ead52-692f-4314-8725-c8a4f4d13a87 has not been provisioned for backup')
+
+    def test_ex_list_available_client_types(self):
+        target = self.driver.list_targets()[0]
+        answer = self.driver.ex_list_available_client_types(target)
+        self.assertEqual(len(answer), 1)
+        self.assertEqual(answer[0].type, 'FA.Linux')
+        self.assertEqual(answer[0].is_file_system, True)
+        self.assertEqual(answer[0].description, 'Linux File system')
+
+    def test_ex_list_available_storage_policies(self):
+        target = self.driver.list_targets()[0]
+        answer = self.driver.ex_list_available_storage_policies(target)
+        self.assertEqual(len(answer), 1)
+        self.assertEqual(answer[0].name,
+                         '30 Day Storage Policy + Secondary Copy')
+        self.assertEqual(answer[0].retention_period, 30)
+        self.assertEqual(answer[0].secondary_location, 'Primary')
+
+    def test_ex_list_available_schedule_policies(self):
+        target = self.driver.list_targets()[0]
+        answer = self.driver.ex_list_available_schedule_policies(target)
+        self.assertEqual(len(answer), 1)
+        self.assertEqual(answer[0].name, '12AM - 6AM')
+        self.assertEqual(answer[0].description, 'Daily backup will start between 12AM - 6AM')
+
+    def test_ex_remove_client_from_target(self):
+        target = self.driver.list_targets()[0]
+        client = self.driver.ex_get_backup_details_for_target('e75ead52-692f-4314-8725-c8a4f4d13a87').clients[0]
+        self.assertTrue(self.driver.ex_remove_client_from_target(target, client))
+
+    def test_ex_remove_client_from_target_STR(self):
+        self.assertTrue(
+            self.driver.ex_remove_client_from_target(
+                'e75ead52-692f-4314-8725-c8a4f4d13a87',
+                '30b1ff76-c76d-4d7c-b39d-3b72be0384c8'
+            )
+        )
+
+    def test_ex_remove_client_from_target_FAIL(self):
+        DimensionDataMockHttp.type = 'FAIL'
+        with self.assertRaises(DimensionDataAPIException) as context:
+            self.driver.ex_remove_client_from_target(
+                'e75ead52-692f-4314-8725-c8a4f4d13a87',
+                '30b1ff76-c76d-4d7c-b39d-3b72be0384c8'
+            )
+        self.assertEqual(context.exception.code, 'ERROR')
+        self.assertTrue('Backup Client is currently performing another operation' in context.exception.msg)
+
+    def test_priv_target_to_target_address(self):
+        target = self.driver.list_targets()[0]
+        self.assertEqual(
+            self.driver._target_to_target_address(target),
+            'e75ead52-692f-4314-8725-c8a4f4d13a87'
+        )
+
+    def test_priv_target_to_target_address_STR(self):
+        self.assertEqual(
+            self.driver._target_to_target_address('e75ead52-692f-4314-8725-c8a4f4d13a87'),
+            'e75ead52-692f-4314-8725-c8a4f4d13a87'
+        )
+
+    def test_priv_target_to_target_address_TYPEERROR(self):
+        with self.assertRaises(TypeError):
+            self.driver._target_to_target_address([1, 2, 3])
+
+    def test_priv_client_to_client_id(self):
+        client = self.driver.ex_get_backup_details_for_target('e75ead52-692f-4314-8725-c8a4f4d13a87').clients[0]
+        self.assertEqual(
+            self.driver._client_to_client_id(client),
+            '30b1ff76-c76d-4d7c-b39d-3b72be0384c8'
+        )
+
+    def test_priv_client_to_client_id_STR(self):
+        self.assertEqual(
+            self.driver._client_to_client_id('30b1ff76-c76d-4d7c-b39d-3b72be0384c8'),
+            '30b1ff76-c76d-4d7c-b39d-3b72be0384c8'
+        )
+
+    def test_priv_client_to_client_id_TYPEERROR(self):
+        with self.assertRaises(TypeError):
+            self.driver._client_to_client_id([1, 2, 3])
+
+
+class InvalidRequestError(Exception):
+    def __init__(self, tag):
+        super(InvalidRequestError, self).__init__("Invalid Request - %s" % tag)
+
+
+class DimensionDataMockHttp(MockHttp):
+
+    fixtures = BackupFileFixtures('dimensiondata')
+
+    def _oec_0_9_myaccount_UNAUTHORIZED(self, method, url, body, headers):
+        return (httplib.UNAUTHORIZED, "", {}, httplib.responses[httplib.UNAUTHORIZED])
+
+    def _oec_0_9_myaccount(self, method, url, body, headers):
+        body = self.fixtures.load('oec_0_9_myaccount.xml')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+    def _oec_0_9_myaccount_EXISTS(self, method, url, body, headers):
+        body = self.fixtures.load('oec_0_9_myaccount.xml')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+    def _oec_0_9_myaccount_DEFAULT(self, method, url, body, headers):
+        body = self.fixtures.load('oec_0_9_myaccount.xml')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+    def _oec_0_9_myaccount_INPROGRESS(self, method, url, body, headers):
+        body = self.fixtures.load('oec_0_9_myaccount.xml')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+    def _oec_0_9_myaccount_FAIL(self, method, url, body, headers):
+        body = self.fixtures.load('oec_0_9_myaccount.xml')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+    def _oec_0_9_myaccount_NOCLIENT(self, method, url, body, headers):
+        body = self.fixtures.load('oec_0_9_myaccount.xml')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+    def _oec_0_9_myaccount_DISABLED(self, method, url, body, headers):
+        body = self.fixtures.load('oec_0_9_myaccount.xml')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+    def _oec_0_9_myaccount_NOJOB(self, method, url, body, headers):
+        body = self.fixtures.load('oec_0_9_myaccount.xml')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_server_e75ead52_692f_4314_8725_c8a4f4d13a87(self, method, url, body, headers):
+        body = self.fixtures.load(
+            'server_server_e75ead52_692f_4314_8725_c8a4f4d13a87.xml')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_server_e75ead52_692f_4314_8725_c8a4f4d13a87_DEFAULT(self, method, url, body, headers):
+        body = self.fixtures.load(
+            'server_server_e75ead52_692f_4314_8725_c8a4f4d13a87_DEFAULT.xml')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_server_e75ead52_692f_4314_8725_c8a4f4d13a87_NOCLIENT(self, method, url, body, headers):
+        body = self.fixtures.load(
+            'server_server_e75ead52_692f_4314_8725_c8a4f4d13a87_DEFAULT.xml')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_server_e75ead52_692f_4314_8725_c8a4f4d13a87_NOJOB(self, method, url, body, headers):
+        body = self.fixtures.load(
+            'server_server_e75ead52_692f_4314_8725_c8a4f4d13a87_DEFAULT.xml')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_server_e75ead52_692f_4314_8725_c8a4f4d13a87_DISABLED(self, method, url, body, headers):
+        body = self.fixtures.load(
+            'server_server_e75ead52_692f_4314_8725_c8a4f4d13a87_DEFAULT.xml')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_server(self, method, url, body, headers):
+        body = self.fixtures.load(
+            'server_server.xml')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+    def _oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_e75ead52_692f_4314_8725_c8a4f4d13a87_backup_client_type(self, method, url, body, headers):
+        body = self.fixtures.load(
+            '_backup_client_type.xml')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+    def _oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_e75ead52_692f_4314_8725_c8a4f4d13a87_backup_client_storagePolicy(
+            self, method, url, body, headers):
+        body = self.fixtures.load(
+            '_backup_client_storagePolicy.xml')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+    def _oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_e75ead52_692f_4314_8725_c8a4f4d13a87_backup_client_schedulePolicy(
+            self, method, url, body, headers):
+        body = self.fixtures.load(
+            '_backup_client_schedulePolicy.xml')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+    def _oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_e75ead52_692f_4314_8725_c8a4f4d13a87_backup_client(
+            self, method, url, body, headers):
+        if method == 'POST':
+            body = self.fixtures.load(
+                '_backup_client_SUCCESS_PUT.xml')
+            return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+        else:
+            raise ValueError("Unknown Method {0}".format(method))
+
+    def _oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_e75ead52_692f_4314_8725_c8a4f4d13a87_backup_NOCLIENT(
+            self, method, url, body, headers):
+        # only gets here are implemented
+        # If we get any other method something has gone wrong
+        assert(method == 'GET')
+        body = self.fixtures.load(
+            '_backup_INFO_NOCLIENT.xml')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+    def _oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_e75ead52_692f_4314_8725_c8a4f4d13a87_backup_DISABLED(
+            self, method, url, body, headers):
+        # only gets here are implemented
+        # If we get any other method something has gone wrong
+        assert(method == 'GET')
+        body = self.fixtures.load(
+            '_backup_INFO_DISABLED.xml')
+        return (httplib.BAD_REQUEST, body, {}, httplib.responses[httplib.OK])
+
+    def _oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_e75ead52_692f_4314_8725_c8a4f4d13a87_backup_NOJOB(
+            self, method, url, body, headers):
+        # only gets here are implemented
+        # If we get any other method something has gone wrong
+        assert(method == 'GET')
+        body = self.fixtures.load(
+            '_backup_INFO_NOJOB.xml')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+    def _oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_e75ead52_692f_4314_8725_c8a4f4d13a87_backup_DEFAULT(
+            self, method, url, body, headers):
+        if method != 'POST':
+            raise InvalidRequestError('Only POST is accepted for this test')
+        request = ET.fromstring(body)
+        service_plan = request.get('servicePlan')
+        if service_plan != DEFAULT_BACKUP_PLAN:
+            raise InvalidRequestError('The default plan %s should have been passed in.  Not %s' % (DEFAULT_BACKUP_PLAN, service_plan))
+        body = self.fixtures.load(
+            '_backup_ENABLE.xml')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+    def _oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_e75ead52_692f_4314_8725_c8a4f4d13a87_backup(
+            self, method, url, body, headers):
+        if method == 'POST':
+            body = self.fixtures.load(
+                '_backup_ENABLE.xml')
+            return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+        elif method == 'GET':
+            if url.endswith('disable'):
+                body = self.fixtures.load(
+                    '_backup_DISABLE.xml')
+                return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+            body = self.fixtures.load(
+                '_backup_INFO.xml')
+            return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+        else:
+            raise ValueError("Unknown Method {0}".format(method))
+
+    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_server_e75ead52_692f_4314_8725_c8a4f4d13a87_NOBACKUP(
+            self, method, url, body, headers):
+        assert(method == 'GET')
+        body = self.fixtures.load('server_server_NOBACKUP.xml')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+    def _oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_e75ead52_692f_4314_8725_c8a4f4d13a87_backup_EXISTS(
+            self, method, url, body, headers):
+        # only POSTs are implemented
+        # If we get any other method something has gone wrong
+        assert(method == 'POST')
+        body = self.fixtures.load(
+            '_backup_EXISTS.xml')
+        return (httplib.BAD_REQUEST, body, {}, httplib.responses[httplib.OK])
+
+    def _oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_e75ead52_692f_4314_8725_c8a4f4d13a87_backup_modify(
+            self, method, url, body, headers):
+        request = ET.fromstring(body)
+        service_plan = request.get('servicePlan')
+        if service_plan != 'Essentials':
+            raise InvalidRequestError("Expected Essentials backup plan in request")
+        body = self.fixtures.load('_backup_modify.xml')
+
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+    def _oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_e75ead52_692f_4314_8725_c8a4f4d13a87_backup_modify_DEFAULT(
+            self, method, url, body, headers):
+        request = ET.fromstring(body)
+        service_plan = request.get('servicePlan')
+        if service_plan != DEFAULT_BACKUP_PLAN:
+            raise InvalidRequestError("Expected % backup plan in test" % DEFAULT_BACKUP_PLAN)
+        body = self.fixtures.load('_backup_modify.xml')
+
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+    def _oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_e75ead52_692f_4314_8725_c8a4f4d13a87_backup_client_30b1ff76_c76d_4d7c_b39d_3b72be0384c8(
+            self, method, url, body, headers):
+        if url.endswith('disable'):
+            body = self.fixtures.load(
+                ('_remove_backup_client.xml')
+            )
+        elif url.endswith('cancelJob'):
+            body = self.fixtures.load(
+                (''
+                 '_backup_client_30b1ff76_c76d_4d7c_b39d_3b72be0384c8_cancelJob.xml')
+            )
+        else:
+            raise ValueError("Unknown URL: %s" % url)
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+    def _oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_e75ead52_692f_4314_8725_c8a4f4d13a87_backup_client_30b1ff76_c76d_4d7c_b39d_3b72be0384c8_FAIL(
+            self, method, url, body, headers):
+        if url.endswith('disable'):
+            body = self.fixtures.load(
+                ('_remove_backup_client_FAIL.xml')
+            )
+        elif url.endswith('cancelJob'):
+            body = self.fixtures.load(
+                (''
+                 '_backup_client_30b1ff76_c76d_4d7c_b39d_3b72be0384c8_cancelJob_FAIL.xml')
+            )
+        else:
+            raise ValueError("Unknown URL: %s" % url)
+        return (httplib.BAD_REQUEST, body, {}, httplib.responses[httplib.OK])
+
+
+if __name__ == '__main__':
+    sys.exit(unittest.main())

http://git-wip-us.apache.org/repos/asf/libcloud/blob/bb1b8104/libcloud/test/backup/test_dimensiondata_v2_4.py
----------------------------------------------------------------------
diff --git a/libcloud/test/backup/test_dimensiondata_v2_4.py b/libcloud/test/backup/test_dimensiondata_v2_4.py
new file mode 100644
index 0000000..d5da857
--- /dev/null
+++ b/libcloud/test/backup/test_dimensiondata_v2_4.py
@@ -0,0 +1,503 @@
+# 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.
+
+try:
+    from lxml import etree as ET
+except ImportError:
+    from xml.etree import ElementTree as ET
+
+import sys
+from libcloud.utils.py3 import httplib
+
+from libcloud.common.dimensiondata import DimensionDataAPIException
+from libcloud.common.types import InvalidCredsError
+from libcloud.backup.base import BackupTargetJob
+from libcloud.backup.drivers.dimensiondata import DimensionDataBackupDriver as DimensionData
+from libcloud.backup.drivers.dimensiondata import DEFAULT_BACKUP_PLAN
+
+from libcloud.test import MockHttp, unittest
+from libcloud.test.backup import TestCaseMixin
+from libcloud.test.file_fixtures import BackupFileFixtures
+
+from libcloud.test.secrets import DIMENSIONDATA_PARAMS
+
+
+class DimensionDataTests(unittest.TestCase, TestCaseMixin):
+
+    def setUp(self):
+        DimensionData.connectionCls.active_api_version = '2.4'
+        DimensionData.connectionCls.conn_classes = (None, DimensionDataMockHttp)
+        DimensionDataMockHttp.type = None
+        self.driver = DimensionData(*DIMENSIONDATA_PARAMS)
+
+    def test_invalid_region(self):
+        with self.assertRaises(ValueError):
+            self.driver = DimensionData(*DIMENSIONDATA_PARAMS, region='blah')
+
+    def test_invalid_creds(self):
+        DimensionDataMockHttp.type = 'UNAUTHORIZED'
+        with self.assertRaises(InvalidCredsError):
+            self.driver.list_targets()
+
+    def test_list_targets(self):
+        targets = self.driver.list_targets()
+        self.assertEqual(len(targets), 2)
+        self.assertEqual(targets[0].id, '5579f3a7-4c32-4cf5-8a7e-b45c36a35c10')
+        self.assertEqual(targets[0].address, 'e75ead52-692f-4314-8725-c8a4f4d13a87')
+        self.assertEqual(targets[0].extra['servicePlan'], 'Enterprise')
+
+    def test_create_target(self):
+        target = self.driver.create_target(
+            'name',
+            'e75ead52-692f-4314-8725-c8a4f4d13a87',
+            extra={'servicePlan': 'Enterprise'})
+        self.assertEqual(target.id, 'ee7c4b64-f7af-4a4f-8384-be362273530f')
+        self.assertEqual(target.address, 'e75ead52-692f-4314-8725-c8a4f4d13a87')
+        self.assertEqual(target.extra['servicePlan'], 'Enterprise')
+
+    def test_create_target_DEFAULT(self):
+        DimensionDataMockHttp.type = 'DEFAULT'
+        target = self.driver.create_target(
+            'name',
+            'e75ead52-692f-4314-8725-c8a4f4d13a87')
+        self.assertEqual(target.id, 'ee7c4b64-f7af-4a4f-8384-be362273530f')
+        self.assertEqual(target.address, 'e75ead52-692f-4314-8725-c8a4f4d13a87')
+
+    def test_create_target_EXISTS(self):
+        DimensionDataMockHttp.type = 'EXISTS'
+        with self.assertRaises(DimensionDataAPIException) as context:
+            self.driver.create_target(
+                'name',
+                'e75ead52-692f-4314-8725-c8a4f4d13a87',
+                extra={'servicePlan': 'Enterprise'})
+        self.assertEqual(context.exception.code, 'ERROR')
+        self.assertEqual(context.exception.msg, 'Cloud backup for this server is already enabled or being enabled (state: NORMAL).')
+
+    def test_update_target(self):
+        target = self.driver.list_targets()[0]
+        extra = {'servicePlan': 'Essentials'}
+        new_target = self.driver.update_target(target, extra=extra)
+        self.assertEqual(new_target.extra['servicePlan'], 'Essentials')
+
+    def test_update_target_DEFAULT(self):
+        DimensionDataMockHttp.type = 'DEFAULT'
+        target = 'e75ead52-692f-4314-8725-c8a4f4d13a87'
+        self.driver.update_target(target)
+
+    def test_update_target_STR(self):
+        target = 'e75ead52-692f-4314-8725-c8a4f4d13a87'
+        extra = {'servicePlan': 'Essentials'}
+        new_target = self.driver.update_target(target, extra=extra)
+        self.assertEqual(new_target.extra['servicePlan'], 'Essentials')
+
+    def test_delete_target(self):
+        target = self.driver.list_targets()[0]
+        self.assertTrue(self.driver.delete_target(target))
+
+    def test_ex_add_client_to_target(self):
+        target = self.driver.list_targets()[0]
+        client = self.driver.ex_list_available_client_types(target)[0]
+        storage_policy = self.driver.ex_list_available_storage_policies(target)[0]
+        schedule_policy = self.driver.ex_list_available_schedule_policies(target)[0]
+        self.assertTrue(
+            self.driver.ex_add_client_to_target(target, client, storage_policy,
+                                                schedule_policy, 'ON_FAILURE', 'nobody@example.com')
+        )
+
+    def test_ex_add_client_to_target_STR(self):
+        self.assertTrue(
+            self.driver.ex_add_client_to_target('e75ead52-692f-4314-8725-c8a4f4d13a87', 'FA.Linux', '14 Day Storage Policy',
+                                                '12AM - 6AM', 'ON_FAILURE', 'nobody@example.com')
+        )
+
+    def test_ex_get_backup_details_for_target(self):
+        target = self.driver.list_targets()[0]
+        response = self.driver.ex_get_backup_details_for_target(target)
+        self.assertEqual(response.service_plan, 'Enterprise')
+        client = response.clients[0]
+        self.assertEqual(client.id, '30b1ff76-c76d-4d7c-b39d-3b72be0384c8')
+        self.assertEqual(client.type.type, 'FA.Linux')
+        self.assertEqual(client.running_job.progress, 5)
+        self.assertTrue(isinstance(client.running_job, BackupTargetJob))
+        self.assertEqual(len(client.alert.notify_list), 2)
+        self.assertTrue(isinstance(client.alert.notify_list, list))
+
+    def test_ex_get_backup_details_for_target_NOBACKUP(self):
+        target = self.driver.list_targets()[0].address
+        DimensionDataMockHttp.type = 'NOBACKUP'
+        response = self.driver.ex_get_backup_details_for_target(target)
+        self.assertTrue(response is None)
+
+    def test_ex_cancel_target_job(self):
+        target = self.driver.list_targets()[0]
+        response = self.driver.ex_get_backup_details_for_target(target)
+        client = response.clients[0]
+        self.assertTrue(isinstance(client.running_job, BackupTargetJob))
+        success = client.running_job.cancel()
+        self.assertTrue(success)
+
+    def test_ex_cancel_target_job_with_extras(self):
+        success = self.driver.cancel_target_job(
+            None,
+            ex_client='30b1ff76_c76d_4d7c_b39d_3b72be0384c8',
+            ex_target='e75ead52_692f_4314_8725_c8a4f4d13a87'
+        )
+        self.assertTrue(success)
+
+    def test_ex_cancel_target_job_FAIL(self):
+        DimensionDataMockHttp.type = 'FAIL'
+        with self.assertRaises(DimensionDataAPIException) as context:
+            self.driver.cancel_target_job(
+                None,
+                ex_client='30b1ff76_c76d_4d7c_b39d_3b72be0384c8',
+                ex_target='e75ead52_692f_4314_8725_c8a4f4d13a87'
+            )
+        self.assertEqual(context.exception.code, 'ERROR')
+
+    """Test a backup info for a target that does not have a client"""
+    def test_ex_get_backup_details_for_target_NO_CLIENT(self):
+        DimensionDataMockHttp.type = 'NOCLIENT'
+        response = self.driver.ex_get_backup_details_for_target('e75ead52-692f-4314-8725-c8a4f4d13a87')
+        self.assertEqual(response.service_plan, 'Essentials')
+        self.assertEqual(len(response.clients), 0)
+
+    """Test a backup details that has a client, but no alerting or running jobs"""
+    def test_ex_get_backup_details_for_target_NO_JOB_OR_ALERT(self):
+        DimensionDataMockHttp.type = 'NOJOB'
+        response = self.driver.ex_get_backup_details_for_target('e75ead52-692f-4314_8725-c8a4f4d13a87')
+        self.assertEqual(response.service_plan, 'Enterprise')
+        self.assertTrue(isinstance(response.clients, list))
+        self.assertEqual(len(response.clients), 1)
+        client = response.clients[0]
+        self.assertEqual(client.id, '30b1ff76-c76d-4d7c-b39d-3b72be0384c8')
+        self.assertEqual(client.type.type, 'FA.Linux')
+        self.assertIsNone(client.running_job)
+        self.assertIsNone(client.alert)
+
+    """Test getting backup info for a server that doesn't exist"""
+    def test_ex_get_backup_details_for_target_DISABLED(self):
+        DimensionDataMockHttp.type = 'DISABLED'
+        with self.assertRaises(DimensionDataAPIException) as context:
+            self.driver.ex_get_backup_details_for_target('e75ead52-692f-4314-8725-c8a4f4d13a87')
+        self.assertEqual(context.exception.code, 'ERROR')
+        self.assertEqual(context.exception.msg, 'Server e75ead52-692f-4314-8725-c8a4f4d13a87 has not been provisioned for backup')
+
+    def test_ex_list_available_client_types(self):
+        target = self.driver.list_targets()[0]
+        answer = self.driver.ex_list_available_client_types(target)
+        self.assertEqual(len(answer), 1)
+        self.assertEqual(answer[0].type, 'FA.Linux')
+        self.assertEqual(answer[0].is_file_system, True)
+        self.assertEqual(answer[0].description, 'Linux File system')
+
+    def test_ex_list_available_storage_policies(self):
+        target = self.driver.list_targets()[0]
+        answer = self.driver.ex_list_available_storage_policies(target)
+        self.assertEqual(len(answer), 1)
+        self.assertEqual(answer[0].name,
+                         '30 Day Storage Policy + Secondary Copy')
+        self.assertEqual(answer[0].retention_period, 30)
+        self.assertEqual(answer[0].secondary_location, 'Primary')
+
+    def test_ex_list_available_schedule_policies(self):
+        target = self.driver.list_targets()[0]
+        answer = self.driver.ex_list_available_schedule_policies(target)
+        self.assertEqual(len(answer), 1)
+        self.assertEqual(answer[0].name, '12AM - 6AM')
+        self.assertEqual(answer[0].description, 'Daily backup will start between 12AM - 6AM')
+
+    def test_ex_remove_client_from_target(self):
+        target = self.driver.list_targets()[0]
+        client = self.driver.ex_get_backup_details_for_target('e75ead52-692f-4314-8725-c8a4f4d13a87').clients[0]
+        self.assertTrue(self.driver.ex_remove_client_from_target(target, client))
+
+    def test_ex_remove_client_from_target_STR(self):
+        self.assertTrue(
+            self.driver.ex_remove_client_from_target(
+                'e75ead52-692f-4314-8725-c8a4f4d13a87',
+                '30b1ff76-c76d-4d7c-b39d-3b72be0384c8'
+            )
+        )
+
+    def test_ex_remove_client_from_target_FAIL(self):
+        DimensionDataMockHttp.type = 'FAIL'
+        with self.assertRaises(DimensionDataAPIException) as context:
+            self.driver.ex_remove_client_from_target(
+                'e75ead52-692f-4314-8725-c8a4f4d13a87',
+                '30b1ff76-c76d-4d7c-b39d-3b72be0384c8'
+            )
+        self.assertEqual(context.exception.code, 'ERROR')
+        self.assertTrue('Backup Client is currently performing another operation' in context.exception.msg)
+
+    def test_priv_target_to_target_address(self):
+        target = self.driver.list_targets()[0]
+        self.assertEqual(
+            self.driver._target_to_target_address(target),
+            'e75ead52-692f-4314-8725-c8a4f4d13a87'
+        )
+
+    def test_priv_target_to_target_address_STR(self):
+        self.assertEqual(
+            self.driver._target_to_target_address('e75ead52-692f-4314-8725-c8a4f4d13a87'),
+            'e75ead52-692f-4314-8725-c8a4f4d13a87'
+        )
+
+    def test_priv_target_to_target_address_TYPEERROR(self):
+        with self.assertRaises(TypeError):
+            self.driver._target_to_target_address([1, 2, 3])
+
+    def test_priv_client_to_client_id(self):
+        client = self.driver.ex_get_backup_details_for_target('e75ead52-692f-4314-8725-c8a4f4d13a87').clients[0]
+        self.assertEqual(
+            self.driver._client_to_client_id(client),
+            '30b1ff76-c76d-4d7c-b39d-3b72be0384c8'
+        )
+
+    def test_priv_client_to_client_id_STR(self):
+        self.assertEqual(
+            self.driver._client_to_client_id('30b1ff76-c76d-4d7c-b39d-3b72be0384c8'),
+            '30b1ff76-c76d-4d7c-b39d-3b72be0384c8'
+        )
+
+    def test_priv_client_to_client_id_TYPEERROR(self):
+        with self.assertRaises(TypeError):
+            self.driver._client_to_client_id([1, 2, 3])
+
+
+class InvalidRequestError(Exception):
+    def __init__(self, tag):
+        super(InvalidRequestError, self).__init__("Invalid Request - %s" % tag)
+
+
+class DimensionDataMockHttp(MockHttp):
+
+    fixtures = BackupFileFixtures('dimensiondata')
+
+    def _oec_0_9_myaccount_UNAUTHORIZED(self, method, url, body, headers):
+        return (httplib.UNAUTHORIZED, "", {}, httplib.responses[httplib.UNAUTHORIZED])
+
+    def _oec_0_9_myaccount(self, method, url, body, headers):
+        body = self.fixtures.load('oec_0_9_myaccount.xml')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+    def _oec_0_9_myaccount_EXISTS(self, method, url, body, headers):
+        body = self.fixtures.load('oec_0_9_myaccount.xml')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+    def _oec_0_9_myaccount_DEFAULT(self, method, url, body, headers):
+        body = self.fixtures.load('oec_0_9_myaccount.xml')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+    def _oec_0_9_myaccount_INPROGRESS(self, method, url, body, headers):
+        body = self.fixtures.load('oec_0_9_myaccount.xml')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+    def _oec_0_9_myaccount_FAIL(self, method, url, body, headers):
+        body = self.fixtures.load('oec_0_9_myaccount.xml')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+    def _oec_0_9_myaccount_NOCLIENT(self, method, url, body, headers):
+        body = self.fixtures.load('oec_0_9_myaccount.xml')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+    def _oec_0_9_myaccount_DISABLED(self, method, url, body, headers):
+        body = self.fixtures.load('oec_0_9_myaccount.xml')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+    def _oec_0_9_myaccount_NOJOB(self, method, url, body, headers):
+        body = self.fixtures.load('oec_0_9_myaccount.xml')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_server_e75ead52_692f_4314_8725_c8a4f4d13a87(self, method, url, body, headers):
+        body = self.fixtures.load(
+            'server_server_e75ead52_692f_4314_8725_c8a4f4d13a87.xml')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_server_e75ead52_692f_4314_8725_c8a4f4d13a87_DEFAULT(self, method, url, body, headers):
+        body = self.fixtures.load(
+            'server_server_e75ead52_692f_4314_8725_c8a4f4d13a87_DEFAULT.xml')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_server_e75ead52_692f_4314_8725_c8a4f4d13a87_NOCLIENT(self, method, url, body, headers):
+        body = self.fixtures.load(
+            'server_server_e75ead52_692f_4314_8725_c8a4f4d13a87_DEFAULT.xml')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_server_e75ead52_692f_4314_8725_c8a4f4d13a87_NOJOB(self, method, url, body, headers):
+        body = self.fixtures.load(
+            'server_server_e75ead52_692f_4314_8725_c8a4f4d13a87_DEFAULT.xml')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_server_e75ead52_692f_4314_8725_c8a4f4d13a87_DISABLED(self, method, url, body, headers):
+        body = self.fixtures.load(
+            'server_server_e75ead52_692f_4314_8725_c8a4f4d13a87_DEFAULT.xml')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_server(self, method, url, body, headers):
+        body = self.fixtures.load(
+            'server_server.xml')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+    def _oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_e75ead52_692f_4314_8725_c8a4f4d13a87_backup_client_type(self, method, url, body, headers):
+        body = self.fixtures.load(
+            '_backup_client_type.xml')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+    def _oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_e75ead52_692f_4314_8725_c8a4f4d13a87_backup_client_storagePolicy(
+            self, method, url, body, headers):
+        body = self.fixtures.load(
+            '_backup_client_storagePolicy.xml')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+    def _oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_e75ead52_692f_4314_8725_c8a4f4d13a87_backup_client_schedulePolicy(
+            self, method, url, body, headers):
+        body = self.fixtures.load(
+            '_backup_client_schedulePolicy.xml')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+    def _oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_e75ead52_692f_4314_8725_c8a4f4d13a87_backup_client(
+            self, method, url, body, headers):
+        if method == 'POST':
+            body = self.fixtures.load(
+                '_backup_client_SUCCESS_PUT.xml')
+            return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+        else:
+            raise ValueError("Unknown Method {0}".format(method))
+
+    def _oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_e75ead52_692f_4314_8725_c8a4f4d13a87_backup_NOCLIENT(
+            self, method, url, body, headers):
+        # only gets here are implemented
+        # If we get any other method something has gone wrong
+        assert(method == 'GET')
+        body = self.fixtures.load(
+            '_backup_INFO_NOCLIENT.xml')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+    def _oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_e75ead52_692f_4314_8725_c8a4f4d13a87_backup_DISABLED(
+            self, method, url, body, headers):
+        # only gets here are implemented
+        # If we get any other method something has gone wrong
+        assert(method == 'GET')
+        body = self.fixtures.load(
+            '_backup_INFO_DISABLED.xml')
+        return (httplib.BAD_REQUEST, body, {}, httplib.responses[httplib.OK])
+
+    def _oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_e75ead52_692f_4314_8725_c8a4f4d13a87_backup_NOJOB(
+            self, method, url, body, headers):
+        # only gets here are implemented
+        # If we get any other method something has gone wrong
+        assert(method == 'GET')
+        body = self.fixtures.load(
+            '_backup_INFO_NOJOB.xml')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+    def _oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_e75ead52_692f_4314_8725_c8a4f4d13a87_backup_DEFAULT(
+            self, method, url, body, headers):
+        if method != 'POST':
+            raise InvalidRequestError('Only POST is accepted for this test')
+        request = ET.fromstring(body)
+        service_plan = request.get('servicePlan')
+        if service_plan != DEFAULT_BACKUP_PLAN:
+            raise InvalidRequestError('The default plan %s should have been passed in.  Not %s' % (DEFAULT_BACKUP_PLAN, service_plan))
+        body = self.fixtures.load(
+            '_backup_ENABLE.xml')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+    def _oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_e75ead52_692f_4314_8725_c8a4f4d13a87_backup(
+            self, method, url, body, headers):
+        if method == 'POST':
+            body = self.fixtures.load(
+                '_backup_ENABLE.xml')
+            return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+        elif method == 'GET':
+            if url.endswith('disable'):
+                body = self.fixtures.load(
+                    '_backup_DISABLE.xml')
+                return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+            body = self.fixtures.load(
+                '_backup_INFO.xml')
+            return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+        else:
+            raise ValueError("Unknown Method {0}".format(method))
+
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_server_e75ead52_692f_4314_8725_c8a4f4d13a87_NOBACKUP(
+            self, method, url, body, headers):
+        assert(method == 'GET')
+        body = self.fixtures.load('server_server_NOBACKUP.xml')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+    def _oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_e75ead52_692f_4314_8725_c8a4f4d13a87_backup_EXISTS(
+            self, method, url, body, headers):
+        # only POSTs are implemented
+        # If we get any other method something has gone wrong
+        assert(method == 'POST')
+        body = self.fixtures.load(
+            '_backup_EXISTS.xml')
+        return (httplib.BAD_REQUEST, body, {}, httplib.responses[httplib.OK])
+
+    def _oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_e75ead52_692f_4314_8725_c8a4f4d13a87_backup_modify(
+            self, method, url, body, headers):
+        request = ET.fromstring(body)
+        service_plan = request.get('servicePlan')
+        if service_plan != 'Essentials':
+            raise InvalidRequestError("Expected Essentials backup plan in request")
+        body = self.fixtures.load('_backup_modify.xml')
+
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+    def _oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_e75ead52_692f_4314_8725_c8a4f4d13a87_backup_modify_DEFAULT(
+            self, method, url, body, headers):
+        request = ET.fromstring(body)
+        service_plan = request.get('servicePlan')
+        if service_plan != DEFAULT_BACKUP_PLAN:
+            raise InvalidRequestError("Expected % backup plan in test" % DEFAULT_BACKUP_PLAN)
+        body = self.fixtures.load('_backup_modify.xml')
+
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+    def _oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_e75ead52_692f_4314_8725_c8a4f4d13a87_backup_client_30b1ff76_c76d_4d7c_b39d_3b72be0384c8(
+            self, method, url, body, headers):
+        if url.endswith('disable'):
+            body = self.fixtures.load(
+                ('_remove_backup_client.xml')
+            )
+        elif url.endswith('cancelJob'):
+            body = self.fixtures.load(
+                (''
+                 '_backup_client_30b1ff76_c76d_4d7c_b39d_3b72be0384c8_cancelJob.xml')
+            )
+        else:
+            raise ValueError("Unknown URL: %s" % url)
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+    def _oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_e75ead52_692f_4314_8725_c8a4f4d13a87_backup_client_30b1ff76_c76d_4d7c_b39d_3b72be0384c8_FAIL(
+            self, method, url, body, headers):
+        if url.endswith('disable'):
+            body = self.fixtures.load(
+                ('_remove_backup_client_FAIL.xml')
+            )
+        elif url.endswith('cancelJob'):
+            body = self.fixtures.load(
+                (''
+                 '_backup_client_30b1ff76_c76d_4d7c_b39d_3b72be0384c8_cancelJob_FAIL.xml')
+            )
+        else:
+            raise ValueError("Unknown URL: %s" % url)
+        return (httplib.BAD_REQUEST, body, {}, httplib.responses[httplib.OK])
+
+
+if __name__ == '__main__':
+    sys.exit(unittest.main())

http://git-wip-us.apache.org/repos/asf/libcloud/blob/bb1b8104/libcloud/test/compute/fixtures/dimensiondata/2.4/image_customerImage.xml
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/dimensiondata/2.4/image_customerImage.xml b/libcloud/test/compute/fixtures/dimensiondata/2.4/image_customerImage.xml
new file mode 100644
index 0000000..4e59e18
--- /dev/null
+++ b/libcloud/test/compute/fixtures/dimensiondata/2.4/image_customerImage.xml
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<customerImages xmlns="urn:didata.com:api:cloud:types" pageNumber="1" pageCount="35" totalCount="35" pageSize="250">
+    <customerImage id="5234e5c7-01de-4411-8b6e-baeb8d91cf5d" datacenterId="NA9">
+        <name>ImportedCustomerImage</name>
+        <description />
+        <operatingSystem id="REDHAT664" displayName="REDHAT6/64" family="UNIX" />
+        <cpu count="4" speed="STANDARD" coresPerSocket="1" />
+        <memoryGb>2</memoryGb>
+        <disk id="1a82316f-23ed-4fe9-b6d8-6b92ac467423" scsiId="0" sizeGb="12" speed="STANDARD" />
+        <createTime>2015-11-19T14:29:02.000Z</createTime>
+        <source type="IMPORT">
+        <artifact type="MF" value="ImportedCustomerImage.mf" date="2015-1119T14:28:54.000Z" />
+        <artifact type="OVF" value="ImportedCustomerImage.ovf" date="2015-1119T14:28:05.000Z" />
+        <artifact type="VMDK" value="ImportedCustomerImage-disk1.vmdk" date="2015-11-19T12:22:31.000Z" /></source>
+        <state>NORMAL</state>
+        <vmwareTools versionStatus="NEED_UPGRADE" runningStatus="NOT_RUNNING" apiVersion="8389" />
+        <virtualHardware version="vmx-10" upToDate="true" />
+    </customerImage>
+    <customerImage id="2ffa36c8-1848-49eb-b4fa-9d908775f68c" datacenterId="NA9">
+        <name>CustomerImageWithPricedSoftwareLabels</name>
+        <description />
+        <operatingSystem id="WIN2008S32" displayName="WIN2008S/32" family="WINDOWS" />
+        <cpu count="1" speed="STANDARD" coresPerSocket="1" />
+        <memoryGb>1</memoryGb>
+        <disk id="29455efc-51af-4b4d-91b3-d81ca0dff7d8" scsiId="0" sizeGb="50" speed="STANDARD" />
+        <softwareLabel>MSSQL2008R2S</softwareLabel>
+        <createTime>2015-11-03T15:25:34.000Z</createTime>
+        <source type="CLONE">
+            <artifact type="SERVER_ID" value="7c9c2551-269d-4274-a247126ba7c6215c" />
+        </source>
+        <state>NORMAL</state>
+        <vmwareTools versionStatus="CURRENT" runningStatus="NOT_RUNNING" />
+        <virtualHardware version="vmx-08" upToDate="false" />
+    </customerImage>
+    <customerImage id="1fc1844f-45d6-4364-b447-f7c7645b47de" datacenterId="NA9">
+        <name>CopiedCustomerImage</name>
+        <description />
+        <operatingSystem id="REDHAT664" displayName="REDHAT6/64" family="UNIX" />
+        <cpu count="1" speed="STANDARD" coresPerSocket="1" />
+        <memoryGb>2</memoryGb>
+        <disk id="42b20819-c161-4dec-aa94-73ec370a6e37" scsiId="0" sizeGb="10" speed="STANDARD" />
+        <createTime>2015-11-11T17:17:00.000Z</createTime>
+        <source type="COPY">
+            <artifact type="IMAGE_ID" value="0b8357b6-f156-4b27-b4fd-b81d09c15efc" />
+        </source>
+        <state>NORMAL</state>
+        <vmwareTools versionStatus="NEED_UPGRADE" runningStatus="NOT_RUNNING" apiVersion="9355" />
+        <virtualHardware version="vmx-10" upToDate="true" />
+    </customerImage>
+</customerImages>

http://git-wip-us.apache.org/repos/asf/libcloud/blob/bb1b8104/libcloud/test/compute/fixtures/dimensiondata/2.4/image_customerImage_2ffa36c8_1848_49eb_b4fa_9d908775f68c.xml
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/dimensiondata/2.4/image_customerImage_2ffa36c8_1848_49eb_b4fa_9d908775f68c.xml b/libcloud/test/compute/fixtures/dimensiondata/2.4/image_customerImage_2ffa36c8_1848_49eb_b4fa_9d908775f68c.xml
new file mode 100644
index 0000000..bff6183
--- /dev/null
+++ b/libcloud/test/compute/fixtures/dimensiondata/2.4/image_customerImage_2ffa36c8_1848_49eb_b4fa_9d908775f68c.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+    <customerImage xmlns="urn:didata.com:api:cloud:types" id="2ffa36c8-1848-49eb-b4fa-9d908775f68c" datacenterId="NA9">
+        <name>CustomerImageWithPricedSoftwareLabels</name>
+        <description />
+        <operatingSystem id="WIN2008S32" displayName="WIN2008S/32" family="WINDOWS" />
+        <cpu count="1" speed="STANDARD" coresPerSocket="1" />
+        <memoryGb>1</memoryGb>
+        <disk id="29455efc-51af-4b4d-91b3-d81ca0dff7d8" scsiId="0" sizeGb="50" speed="STANDARD" />
+        <softwareLabel>MSSQL2008R2S</softwareLabel>
+        <createTime>2015-11-03T15:25:34.000Z</createTime>
+        <source type="CLONE">
+            <artifact type="SERVER_ID" value="7c9c2551-269d-4274-a247126ba7c6215c" />
+        </source>
+        <state>NORMAL</state>
+        <vmwareTools versionStatus="CURRENT" runningStatus="NOT_RUNNING" />
+        <virtualHardware version="vmx-08" upToDate="false" />
+    </customerImage>

http://git-wip-us.apache.org/repos/asf/libcloud/blob/bb1b8104/libcloud/test/compute/fixtures/dimensiondata/2.4/image_customerImage_5234e5c7_01de_4411_8b6e_baeb8d91cf5d.xml
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/dimensiondata/2.4/image_customerImage_5234e5c7_01de_4411_8b6e_baeb8d91cf5d.xml b/libcloud/test/compute/fixtures/dimensiondata/2.4/image_customerImage_5234e5c7_01de_4411_8b6e_baeb8d91cf5d.xml
new file mode 100644
index 0000000..db5302d
--- /dev/null
+++ b/libcloud/test/compute/fixtures/dimensiondata/2.4/image_customerImage_5234e5c7_01de_4411_8b6e_baeb8d91cf5d.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+    <customerImage xmlns="urn:didata.com:api:cloud:types" id="5234e5c7-01de-4411-8b6e-baeb8d91cf5d" datacenterId="NA9">
+        <name>ImportedCustomerImage</name>
+        <description />
+        <operatingSystem id="REDHAT664" displayName="REDHAT6/64" family="UNIX" />
+        <cpu count="4" speed="STANDARD" coresPerSocket="1" />
+        <memoryGb>2</memoryGb>
+        <disk id="1a82316f-23ed-4fe9-b6d8-6b92ac467423" scsiId="0" sizeGb="12" speed="STANDARD" />
+        <createTime>2015-11-19T14:29:02.000Z</createTime>
+        <source type="IMPORT">
+        <artifact type="MF" value="ImportedCustomerImage.mf" date="2015-1119T14:28:54.000Z" />
+        <artifact type="OVF" value="ImportedCustomerImage.ovf" date="2015-1119T14:28:05.000Z" />
+        <artifact type="VMDK" value="ImportedCustomerImage-disk1.vmdk" date="2015-11-19T12:22:31.000Z" /></source>
+        <state>NORMAL</state>
+        <vmwareTools versionStatus="NEED_UPGRADE" runningStatus="NOT_RUNNING" apiVersion="8389" />
+        <virtualHardware version="vmx-10" upToDate="true" />
+    </customerImage>


[28/40] libcloud git commit: Attempt workaround 2 for pylint bug on travis CI

Posted by an...@apache.org.
Attempt workaround 2 for pylint bug on travis CI


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

Branch: refs/heads/trunk
Commit: d2486ec8437c7bdf209bc1cf6990c565065f7e6a
Parents: 75da6d8
Author: Samuel Chong <sa...@gmail.com>
Authored: Tue Nov 22 11:19:50 2016 +1100
Committer: Samuel Chong <sa...@gmail.com>
Committed: Tue Nov 22 11:19:50 2016 +1100

----------------------------------------------------------------------
 libcloud/common/dimensiondata.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/libcloud/blob/d2486ec8/libcloud/common/dimensiondata.py
----------------------------------------------------------------------
diff --git a/libcloud/common/dimensiondata.py b/libcloud/common/dimensiondata.py
index 22f1da8..a665eed 100644
--- a/libcloud/common/dimensiondata.py
+++ b/libcloud/common/dimensiondata.py
@@ -18,7 +18,7 @@ Dimension Data Common Components
 from base64 import b64encode
 from time import sleep
 
-from distutils.version import LooseVersion  # pylint: disable=import-error
+from distutils.version import LooseVersion  # pylint: disable-msg=E0611
 from libcloud.utils.py3 import httplib
 from libcloud.utils.py3 import b
 from libcloud.common.base import ConnectionUserAndKey, XmlResponse, RawResponse


[13/40] libcloud git commit: Fix merge conflict

Posted by an...@apache.org.
Fix merge conflict


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

Branch: refs/heads/trunk
Commit: e846f57b57f70d93d7ff4d18e12bda32f921e9da
Parents: 1252120 cd7fe0e
Author: Samuel Chong <sa...@gmail.com>
Authored: Tue Nov 15 11:49:14 2016 +1100
Committer: Samuel Chong <sa...@gmail.com>
Committed: Tue Nov 15 11:49:14 2016 +1100

----------------------------------------------------------------------
 libcloud/common/dimensiondata.py | 13 ++++++++-----
 1 file changed, 8 insertions(+), 5 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/libcloud/blob/e846f57b/libcloud/common/dimensiondata.py
----------------------------------------------------------------------
diff --cc libcloud/common/dimensiondata.py
index b7a0b18,3cb9f66..198fa02
--- a/libcloud/common/dimensiondata.py
+++ b/libcloud/common/dimensiondata.py
@@@ -380,13 -376,13 +381,13 @@@ class DimensionDataConnection(Connectio
      api_version_1 = 0.9
  
      # Earliest version supported
-     oldest_api_version = 2.2
+     oldest_api_version = '2.2'
  
      # Latest version supported
-     latest_api_version = 2.4
 -    latest_api_version = '2.3'
++    latest_api_version = '2.4'
  
      # Default api version
-     active_api_version = 2.4
+     active_api_version = '2.3'
  
      _orgId = None
      responseCls = DimensionDataResponse


[35/40] libcloud git commit: Fix line over hanging issue in test

Posted by an...@apache.org.
Fix line over hanging issue in test


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

Branch: refs/heads/trunk
Commit: b27bbe075779cd0a721d9ca57ebde6d5a3d35dc9
Parents: d1c3259
Author: Samuel Chong <sa...@gmail.com>
Authored: Fri Nov 25 11:45:50 2016 +1100
Committer: Samuel Chong <sa...@gmail.com>
Committed: Fri Nov 25 11:45:50 2016 +1100

----------------------------------------------------------------------
 libcloud/test/compute/test_dimensiondata_v2_4.py | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/libcloud/blob/b27bbe07/libcloud/test/compute/test_dimensiondata_v2_4.py
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/test_dimensiondata_v2_4.py b/libcloud/test/compute/test_dimensiondata_v2_4.py
index 15c29f8..f16eb26 100644
--- a/libcloud/test/compute/test_dimensiondata_v2_4.py
+++ b/libcloud/test/compute/test_dimensiondata_v2_4.py
@@ -2067,8 +2067,8 @@ class DimensionData_v2_4_Tests(unittest.TestCase, TestCaseMixin):
 
     def test_exchange_nic_vlans(self):
         success = self.driver.ex_exchange_nic_vlans(
-                      nic_id_1='a4b4b42b-ccb5-416f-b052-ce7cb7fdff12',
-                      nic_id_2='b39d09b8-ea65-424a-8fa6-c6f5a98afc69')
+            nic_id_1='a4b4b42b-ccb5-416f-b052-ce7cb7fdff12',
+            nic_id_2='b39d09b8-ea65-424a-8fa6-c6f5a98afc69')
         self.assertTrue(success)
 
     def test_change_nic_network_adapter(self):


[22/40] libcloud git commit: Unit test for import image

Posted by an...@apache.org.
Unit test for import image


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

Branch: refs/heads/trunk
Commit: 4189872dac0d5b58158fc968bcc127fca140a139
Parents: 1bafa61
Author: Samuel Chong <sa...@gmail.com>
Authored: Thu Nov 17 11:02:15 2016 +1100
Committer: Samuel Chong <sa...@gmail.com>
Committed: Thu Nov 17 11:02:15 2016 +1100

----------------------------------------------------------------------
 .../dimensiondata/2.4/import_image_response.xml    |  8 ++++++++
 libcloud/test/compute/test_dimensiondata_v2_4.py   | 17 +++++++++++++++++
 2 files changed, 25 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/libcloud/blob/4189872d/libcloud/test/compute/fixtures/dimensiondata/2.4/import_image_response.xml
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/dimensiondata/2.4/import_image_response.xml b/libcloud/test/compute/fixtures/dimensiondata/2.4/import_image_response.xml
new file mode 100644
index 0000000..b51b0bf
--- /dev/null
+++ b/libcloud/test/compute/fixtures/dimensiondata/2.4/import_image_response.xml
@@ -0,0 +1,8 @@
+<response requestId= "na/2014-04-14T13:37:20/62f06368-c3fb-11e3-b29c-001517c4643e"
+xmlns= "urn:didata.com:api:cloud:types" >
+   <operation>IMPORT_IMAGE</operation>
+   <responseCode>IN_PROGRESS</responseCode>
+   <message>Request to import image has been accepted and is being
+processed.</message>
+   <info name="imageId" value="3389ffe8-c3fc-11e3-b29c-001517c4643e"/>
+</response>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/libcloud/blob/4189872d/libcloud/test/compute/test_dimensiondata_v2_4.py
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/test_dimensiondata_v2_4.py b/libcloud/test/compute/test_dimensiondata_v2_4.py
index 30f5642..7a2ba63 100644
--- a/libcloud/test/compute/test_dimensiondata_v2_4.py
+++ b/libcloud/test/compute/test_dimensiondata_v2_4.py
@@ -2028,6 +2028,16 @@ class DimensionData_v2_4_Tests(unittest.TestCase, TestCaseMixin):
             ex_portlist=portlist.id)
         self.assertTrue(success)
 
+    def test_import_image(self):
+        tag_dictionaries = {'tagkey1_name': 'dev test', 'tagkey2_name': None}
+        success = self.driver.import_image(
+            ovf_package_name='aTestGocToNGoc2_export2.mf',
+            name='Libcloud NGOCImage_New 2',
+            description='test',
+            cluster_id='QA1_N2_VMWARE_1-01',
+            is_guest_os_customization='false',
+            tagkey_name_value_dictionaries=tag_dictionaries)
+        self.assertTrue(success)
 
 class InvalidRequestError(Exception):
     def __init__(self, tag):
@@ -3285,5 +3295,12 @@ class DimensionDataMockHttp(StorageMockHttp, MockHttp):
         )
         return httplib.OK, body, {}, httplib.responses[httplib.OK]
 
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_image_importImage(
+        self, method, url, body, headers):
+        body = self.fixtures.load(
+            '2.4/import_image_response.xml'
+        )
+        return httplib.OK, body, {}, httplib.responses[httplib.OK]
+
 if __name__ == '__main__':
     sys.exit(unittest.main())


[06/40] libcloud git commit: Update DD node driver comments

Posted by an...@apache.org.
Update DD node driver comments


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

Branch: refs/heads/trunk
Commit: 3b947b311940bdd0fa75a03029095db34eb7a605
Parents: 75111a4
Author: Samuel Chong <sa...@gmail.com>
Authored: Tue Nov 8 15:41:41 2016 +1100
Committer: Samuel Chong <sa...@gmail.com>
Committed: Tue Nov 8 15:41:41 2016 +1100

----------------------------------------------------------------------
 libcloud/compute/drivers/dimensiondata.py | 1 +
 1 file changed, 1 insertion(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/libcloud/blob/3b947b31/libcloud/compute/drivers/dimensiondata.py
----------------------------------------------------------------------
diff --git a/libcloud/compute/drivers/dimensiondata.py b/libcloud/compute/drivers/dimensiondata.py
index 13914e3..ff3a5d8 100644
--- a/libcloud/compute/drivers/dimensiondata.py
+++ b/libcloud/compute/drivers/dimensiondata.py
@@ -95,6 +95,7 @@ OBJECT_TO_TAGGING_ASSET_TYPE_MAP = {
 class DimensionDataNodeDriver(NodeDriver):
     """
     DimensionData node driver.
+    Default api_version is used unless specified.
     """
 
     selected_region = None


[33/40] libcloud git commit: Merge update for version compare and fix pylint issues

Posted by an...@apache.org.
Merge update for version compare and fix pylint issues


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

Branch: refs/heads/trunk
Commit: ba6346f7871ffc9451d5c3f45dafc516383d94f8
Parents: 4284c31
Author: Samuel Chong <sa...@gmail.com>
Authored: Fri Nov 25 11:12:16 2016 +1100
Committer: Samuel Chong <sa...@gmail.com>
Committed: Fri Nov 25 11:12:16 2016 +1100

----------------------------------------------------------------------
 libcloud/compute/drivers/dimensiondata.py | 9 ++++-----
 1 file changed, 4 insertions(+), 5 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/libcloud/blob/ba6346f7/libcloud/compute/drivers/dimensiondata.py
----------------------------------------------------------------------
diff --git a/libcloud/compute/drivers/dimensiondata.py b/libcloud/compute/drivers/dimensiondata.py
index 1455588..b0f248a 100644
--- a/libcloud/compute/drivers/dimensiondata.py
+++ b/libcloud/compute/drivers/dimensiondata.py
@@ -21,7 +21,7 @@ try:
 except ImportError:
     from xml.etree import ElementTree as ET
 
-from distutils.version import LooseVersion, StrictVersion
+from libcloud.common.dimensiondata import LooseVersion
 from libcloud.common.exceptions import BaseHTTPError
 from libcloud.compute.base import NodeDriver, Node, NodeAuthPassword
 from libcloud.compute.base import NodeSize, NodeImage, NodeLocation
@@ -904,7 +904,7 @@ class DimensionDataNodeDriver(NodeDriver):
         # Unsupported for version lower than 2.4
         if LooseVersion(self.connection.active_api_version) < LooseVersion(
                 '2.4'):
-            raise Exception("import image is feature is NOT supported in  " \
+            raise Exception("import image is feature is NOT supported in  "
                             "api version earlier than 2.4")
         elif cluster_id is None and datacenter_id is None:
             raise ValueError("Either cluster_id or datacenter_id must be "
@@ -2545,8 +2545,8 @@ class DimensionDataNodeDriver(NodeDriver):
         # Version 2.4 and higher
         else:
             clone_server_elem = ET.Element('cloneServer',
-                                             {'id': node_id,
-                                              'xmlns': TYPES_URN})
+                                           {'id': node_id,
+                                            'xmlns': TYPES_URN})
 
             ET.SubElement(clone_server_elem, 'imageName').text = image_name
 
@@ -3730,7 +3730,6 @@ class DimensionDataNodeDriver(NodeDriver):
         response_code = findtext(response, 'responseCode', TYPES_URN)
         return response_code in ['IN_PROGRESS', 'OK']
 
-
     def ex_exchange_nic_vlans(self, nic_id_1, nic_id_2):
         """
         Exchange NIC Vlans


[10/40] libcloud git commit: Update active api version to 2.4

Posted by an...@apache.org.
Update active api version to 2.4


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

Branch: refs/heads/trunk
Commit: 2b97294b8beee1638aa49ba11e9259cad668ac4f
Parents: 53c6c97
Author: Samuel Chong <sa...@gmail.com>
Authored: Wed Nov 9 16:09:33 2016 +1100
Committer: Samuel Chong <sa...@gmail.com>
Committed: Wed Nov 9 16:09:33 2016 +1100

----------------------------------------------------------------------
 libcloud/common/dimensiondata.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/libcloud/blob/2b97294b/libcloud/common/dimensiondata.py
----------------------------------------------------------------------
diff --git a/libcloud/common/dimensiondata.py b/libcloud/common/dimensiondata.py
index bf2631e..b7a0b18 100644
--- a/libcloud/common/dimensiondata.py
+++ b/libcloud/common/dimensiondata.py
@@ -386,7 +386,7 @@ class DimensionDataConnection(ConnectionUserAndKey):
     latest_api_version = 2.4
 
     # Default api version
-    active_api_version = 2.3
+    active_api_version = 2.4
 
     _orgId = None
     responseCls = DimensionDataResponse


[03/40] libcloud git commit: Upgrade OS Image and Customer Image for caas api 2.4

Posted by an...@apache.org.
Upgrade OS Image and Customer Image for caas api 2.4


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

Branch: refs/heads/trunk
Commit: 03a2aa4e341ddda803104fb6bfa862ea05430afd
Parents: f4caab3
Author: Samuel Chong <sa...@gmail.com>
Authored: Mon Nov 7 12:54:47 2016 +1100
Committer: Samuel Chong <sa...@gmail.com>
Committed: Mon Nov 7 12:54:47 2016 +1100

----------------------------------------------------------------------
 libcloud/common/dimensiondata.py                |   9 +-
 libcloud/compute/drivers/dimensiondata.py       |   4 +-
 libcloud/test/backup/test_dimensiondata.py      |  14 +-
 .../dimensiondata/image_customerImage.xml       |  29 ++-
 ...age_2ffa36c8_1848_49eb_b4fa_9d908775f68c.xml |  10 +-
 ...age_5234e5c7_01de_4411_8b6e_baeb8d91cf5d.xml |  20 +-
 .../fixtures/dimensiondata/image_osImage.xml    |  35 +--
 ...age_6b4fb0c7_a57b_4f58_b59c_9958f94f971a.xml |  19 +-
 ...age_c14b1a46_2428_44c1_9c1a_b20e6418d08c.xml |  19 +-
 libcloud/test/compute/test_dimensiondata.py     | 216 +++++++++----------
 .../test/loadbalancer/test_dimensiondata.py     |  44 ++--
 11 files changed, 230 insertions(+), 189 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/libcloud/blob/03a2aa4e/libcloud/common/dimensiondata.py
----------------------------------------------------------------------
diff --git a/libcloud/common/dimensiondata.py b/libcloud/common/dimensiondata.py
index 0a868b8..73443e3 100644
--- a/libcloud/common/dimensiondata.py
+++ b/libcloud/common/dimensiondata.py
@@ -268,6 +268,11 @@ API_ENDPOINTS = {
         'host': 'afapi.bsnlcloud.com',
         'vendor': 'BSNL'
     },
+    'dd-qa': {
+        'name': 'Test(QA)',
+        'host': 'apiqa1geo1.itaas.dimensiondata.com',
+        'vendor': 'DimensionData'
+    }
 }
 
 # Default API end-point for the base connection class.
@@ -373,7 +378,7 @@ class DimensionDataConnection(ConnectionUserAndKey):
     api_path_version_1 = '/oec'
     api_path_version_2 = '/caas'
     api_version_1 = '0.9'
-    api_version_2 = '2.3'
+    api_version_2 = '2.4'
 
     _orgId = None
     responseCls = DimensionDataResponse
@@ -446,7 +451,7 @@ class DimensionDataConnection(ConnectionUserAndKey):
     def request_with_orgId_api_2(self, action, params=None, data='',
                                  headers=None, method='GET'):
         action = "%s/%s" % (self.get_resource_path_api_2(), action)
-
+        print(action)
         return super(DimensionDataConnection, self).request(
             action=action,
             params=params, data=data,

http://git-wip-us.apache.org/repos/asf/libcloud/blob/03a2aa4e/libcloud/compute/drivers/dimensiondata.py
----------------------------------------------------------------------
diff --git a/libcloud/compute/drivers/dimensiondata.py b/libcloud/compute/drivers/dimensiondata.py
index 9e477b6..d95bbb3 100644
--- a/libcloud/compute/drivers/dimensiondata.py
+++ b/libcloud/compute/drivers/dimensiondata.py
@@ -3651,8 +3651,10 @@ class DimensionDataNodeDriver(NodeDriver):
             locations = self.list_locations(location_id)
         location = list(filter(lambda x: x.id == location_id,
                                locations))[0]
+
         cpu_spec = self._to_cpu_spec(element.find(fixxpath('cpu', TYPES_URN)))
-        os_el = element.find(fixxpath('operatingSystem', TYPES_URN))
+        os_el = element.find(fixxpath('guest/operatingSystem', TYPES_URN))
+
         if element.tag.endswith('customerImage'):
             is_customer_image = True
         else:

http://git-wip-us.apache.org/repos/asf/libcloud/blob/03a2aa4e/libcloud/test/backup/test_dimensiondata.py
----------------------------------------------------------------------
diff --git a/libcloud/test/backup/test_dimensiondata.py b/libcloud/test/backup/test_dimensiondata.py
index b2f599c..3214cff 100644
--- a/libcloud/test/backup/test_dimensiondata.py
+++ b/libcloud/test/backup/test_dimensiondata.py
@@ -319,32 +319,32 @@ class DimensionDataMockHttp(MockHttp):
         body = self.fixtures.load('oec_0_9_myaccount.xml')
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
-    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_server_e75ead52_692f_4314_8725_c8a4f4d13a87(self, method, url, body, headers):
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_server_e75ead52_692f_4314_8725_c8a4f4d13a87(self, method, url, body, headers):
         body = self.fixtures.load(
             'server_server_e75ead52_692f_4314_8725_c8a4f4d13a87.xml')
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
-    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_server_e75ead52_692f_4314_8725_c8a4f4d13a87_DEFAULT(self, method, url, body, headers):
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_server_e75ead52_692f_4314_8725_c8a4f4d13a87_DEFAULT(self, method, url, body, headers):
         body = self.fixtures.load(
             'server_server_e75ead52_692f_4314_8725_c8a4f4d13a87_DEFAULT.xml')
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
-    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_server_e75ead52_692f_4314_8725_c8a4f4d13a87_NOCLIENT(self, method, url, body, headers):
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_server_e75ead52_692f_4314_8725_c8a4f4d13a87_NOCLIENT(self, method, url, body, headers):
         body = self.fixtures.load(
             'server_server_e75ead52_692f_4314_8725_c8a4f4d13a87_DEFAULT.xml')
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
-    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_server_e75ead52_692f_4314_8725_c8a4f4d13a87_NOJOB(self, method, url, body, headers):
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_server_e75ead52_692f_4314_8725_c8a4f4d13a87_NOJOB(self, method, url, body, headers):
         body = self.fixtures.load(
             'server_server_e75ead52_692f_4314_8725_c8a4f4d13a87_DEFAULT.xml')
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
-    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_server_e75ead52_692f_4314_8725_c8a4f4d13a87_DISABLED(self, method, url, body, headers):
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_server_e75ead52_692f_4314_8725_c8a4f4d13a87_DISABLED(self, method, url, body, headers):
         body = self.fixtures.load(
             'server_server_e75ead52_692f_4314_8725_c8a4f4d13a87_DEFAULT.xml')
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
-    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_server(self, method, url, body, headers):
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_server(self, method, url, body, headers):
         body = self.fixtures.load(
             'server_server.xml')
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
@@ -432,7 +432,7 @@ class DimensionDataMockHttp(MockHttp):
         else:
             raise ValueError("Unknown Method {0}".format(method))
 
-    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_server_e75ead52_692f_4314_8725_c8a4f4d13a87_NOBACKUP(
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_server_e75ead52_692f_4314_8725_c8a4f4d13a87_NOBACKUP(
             self, method, url, body, headers):
         assert(method == 'GET')
         body = self.fixtures.load('server_server_NOBACKUP.xml')

http://git-wip-us.apache.org/repos/asf/libcloud/blob/03a2aa4e/libcloud/test/compute/fixtures/dimensiondata/image_customerImage.xml
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/dimensiondata/image_customerImage.xml b/libcloud/test/compute/fixtures/dimensiondata/image_customerImage.xml
index 4e59e18..0415d65 100644
--- a/libcloud/test/compute/fixtures/dimensiondata/image_customerImage.xml
+++ b/libcloud/test/compute/fixtures/dimensiondata/image_customerImage.xml
@@ -3,23 +3,25 @@
     <customerImage id="5234e5c7-01de-4411-8b6e-baeb8d91cf5d" datacenterId="NA9">
         <name>ImportedCustomerImage</name>
         <description />
-        <operatingSystem id="REDHAT664" displayName="REDHAT6/64" family="UNIX" />
         <cpu count="4" speed="STANDARD" coresPerSocket="1" />
         <memoryGb>2</memoryGb>
         <disk id="1a82316f-23ed-4fe9-b6d8-6b92ac467423" scsiId="0" sizeGb="12" speed="STANDARD" />
         <createTime>2015-11-19T14:29:02.000Z</createTime>
         <source type="IMPORT">
-        <artifact type="MF" value="ImportedCustomerImage.mf" date="2015-1119T14:28:54.000Z" />
-        <artifact type="OVF" value="ImportedCustomerImage.ovf" date="2015-1119T14:28:05.000Z" />
-        <artifact type="VMDK" value="ImportedCustomerImage-disk1.vmdk" date="2015-11-19T12:22:31.000Z" /></source>
-        <state>NORMAL</state>
-        <vmwareTools versionStatus="NEED_UPGRADE" runningStatus="NOT_RUNNING" apiVersion="8389" />
+            <artifact type="MF" value="ImportedCustomerImage.mf" date="2015-1119T14:28:54.000Z" />
+            <artifact type="OVF" value="ImportedCustomerImage.ovf" date="2015-1119T14:28:05.000Z" />
+            <artifact type="VMDK" value="ImportedCustomerImage-disk1.vmdk" date="2015-11-19T12:22:31.000Z" />
+        </source>
         <virtualHardware version="vmx-10" upToDate="true" />
+        <state>NORMAL</state>
+        <guest osCustomization="true">
+            <operatingSystem id="REDHAT664" displayName="REDHAT6/64" family="UNIX"/>
+            <vmTools type="vmx-08" versionStatus="NEED_UPGRADE" runningStatus="NOT_RUNNING" apiVersion="8389"/>
+        </guest>
     </customerImage>
     <customerImage id="2ffa36c8-1848-49eb-b4fa-9d908775f68c" datacenterId="NA9">
         <name>CustomerImageWithPricedSoftwareLabels</name>
         <description />
-        <operatingSystem id="WIN2008S32" displayName="WIN2008S/32" family="WINDOWS" />
         <cpu count="1" speed="STANDARD" coresPerSocket="1" />
         <memoryGb>1</memoryGb>
         <disk id="29455efc-51af-4b4d-91b3-d81ca0dff7d8" scsiId="0" sizeGb="50" speed="STANDARD" />
@@ -29,13 +31,16 @@
             <artifact type="SERVER_ID" value="7c9c2551-269d-4274-a247126ba7c6215c" />
         </source>
         <state>NORMAL</state>
-        <vmwareTools versionStatus="CURRENT" runningStatus="NOT_RUNNING" />
         <virtualHardware version="vmx-08" upToDate="false" />
+        <guest osCustomization="true">
+            <operatingSystem id="WIN2008S32" displayName="WIN2008S/32" family="WINDOWS" />
+            <vmTools type="vmx-08" versionStatus="CURRENT"
+                     runningStatus="NOT_RUNNING" />
+        </guest>
     </customerImage>
     <customerImage id="1fc1844f-45d6-4364-b447-f7c7645b47de" datacenterId="NA9">
         <name>CopiedCustomerImage</name>
         <description />
-        <operatingSystem id="REDHAT664" displayName="REDHAT6/64" family="UNIX" />
         <cpu count="1" speed="STANDARD" coresPerSocket="1" />
         <memoryGb>2</memoryGb>
         <disk id="42b20819-c161-4dec-aa94-73ec370a6e37" scsiId="0" sizeGb="10" speed="STANDARD" />
@@ -44,7 +49,11 @@
             <artifact type="IMAGE_ID" value="0b8357b6-f156-4b27-b4fd-b81d09c15efc" />
         </source>
         <state>NORMAL</state>
-        <vmwareTools versionStatus="NEED_UPGRADE" runningStatus="NOT_RUNNING" apiVersion="9355" />
         <virtualHardware version="vmx-10" upToDate="true" />
+        <guest osCustomization="true">
+            <operatingSystem id="REDHAT664" displayName="REDHAT6/64" family="UNIX" />
+            <vmTools type="vmx-08" versionStatus="NEED_UPGRADE"
+                     runningStatus="NOT_RUNNING" apiVersion="9355" />
+        </guest>
     </customerImage>
 </customerImages>

http://git-wip-us.apache.org/repos/asf/libcloud/blob/03a2aa4e/libcloud/test/compute/fixtures/dimensiondata/image_customerImage_2ffa36c8_1848_49eb_b4fa_9d908775f68c.xml
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/dimensiondata/image_customerImage_2ffa36c8_1848_49eb_b4fa_9d908775f68c.xml b/libcloud/test/compute/fixtures/dimensiondata/image_customerImage_2ffa36c8_1848_49eb_b4fa_9d908775f68c.xml
index bff6183..20627e1 100644
--- a/libcloud/test/compute/fixtures/dimensiondata/image_customerImage_2ffa36c8_1848_49eb_b4fa_9d908775f68c.xml
+++ b/libcloud/test/compute/fixtures/dimensiondata/image_customerImage_2ffa36c8_1848_49eb_b4fa_9d908775f68c.xml
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="UTF-8"?>
-    <customerImage xmlns="urn:didata.com:api:cloud:types" id="2ffa36c8-1848-49eb-b4fa-9d908775f68c" datacenterId="NA9">
+    <customerImage xmlns="urn:didata.com:api:cloud:types"
+                   id="2ffa36c8-1848-49eb-b4fa-9d908775f68c" datacenterId="NA9">
         <name>CustomerImageWithPricedSoftwareLabels</name>
         <description />
-        <operatingSystem id="WIN2008S32" displayName="WIN2008S/32" family="WINDOWS" />
         <cpu count="1" speed="STANDARD" coresPerSocket="1" />
         <memoryGb>1</memoryGb>
         <disk id="29455efc-51af-4b4d-91b3-d81ca0dff7d8" scsiId="0" sizeGb="50" speed="STANDARD" />
@@ -12,6 +12,10 @@
             <artifact type="SERVER_ID" value="7c9c2551-269d-4274-a247126ba7c6215c" />
         </source>
         <state>NORMAL</state>
-        <vmwareTools versionStatus="CURRENT" runningStatus="NOT_RUNNING" />
         <virtualHardware version="vmx-08" upToDate="false" />
+        <guest osCustomization="true">
+            <operatingSystem id="WIN2008S32" displayName="WIN2008S/32" family="WINDOWS" />
+            <vmTools type="vmx-08" versionStatus="CURRENT"
+                     runningStatus="NOT_RUNNING" />
+        </guest>
     </customerImage>

http://git-wip-us.apache.org/repos/asf/libcloud/blob/03a2aa4e/libcloud/test/compute/fixtures/dimensiondata/image_customerImage_5234e5c7_01de_4411_8b6e_baeb8d91cf5d.xml
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/dimensiondata/image_customerImage_5234e5c7_01de_4411_8b6e_baeb8d91cf5d.xml b/libcloud/test/compute/fixtures/dimensiondata/image_customerImage_5234e5c7_01de_4411_8b6e_baeb8d91cf5d.xml
index db5302d..f8ba258 100644
--- a/libcloud/test/compute/fixtures/dimensiondata/image_customerImage_5234e5c7_01de_4411_8b6e_baeb8d91cf5d.xml
+++ b/libcloud/test/compute/fixtures/dimensiondata/image_customerImage_5234e5c7_01de_4411_8b6e_baeb8d91cf5d.xml
@@ -1,17 +1,21 @@
 <?xml version="1.0" encoding="UTF-8"?>
-    <customerImage xmlns="urn:didata.com:api:cloud:types" id="5234e5c7-01de-4411-8b6e-baeb8d91cf5d" datacenterId="NA9">
+<customerImage  xmlns="urn:didata.com:api:cloud:types"
+                id="5234e5c7-01de-4411-8b6e-baeb8d91cf5d" datacenterId="NA9">
         <name>ImportedCustomerImage</name>
         <description />
-        <operatingSystem id="REDHAT664" displayName="REDHAT6/64" family="UNIX" />
         <cpu count="4" speed="STANDARD" coresPerSocket="1" />
         <memoryGb>2</memoryGb>
         <disk id="1a82316f-23ed-4fe9-b6d8-6b92ac467423" scsiId="0" sizeGb="12" speed="STANDARD" />
         <createTime>2015-11-19T14:29:02.000Z</createTime>
         <source type="IMPORT">
-        <artifact type="MF" value="ImportedCustomerImage.mf" date="2015-1119T14:28:54.000Z" />
-        <artifact type="OVF" value="ImportedCustomerImage.ovf" date="2015-1119T14:28:05.000Z" />
-        <artifact type="VMDK" value="ImportedCustomerImage-disk1.vmdk" date="2015-11-19T12:22:31.000Z" /></source>
-        <state>NORMAL</state>
-        <vmwareTools versionStatus="NEED_UPGRADE" runningStatus="NOT_RUNNING" apiVersion="8389" />
+            <artifact type="MF" value="ImportedCustomerImage.mf" date="2015-1119T14:28:54.000Z" />
+            <artifact type="OVF" value="ImportedCustomerImage.ovf" date="2015-1119T14:28:05.000Z" />
+            <artifact type="VMDK" value="ImportedCustomerImage-disk1.vmdk" date="2015-11-19T12:22:31.000Z" />
+        </source>
         <virtualHardware version="vmx-10" upToDate="true" />
-    </customerImage>
+        <state>NORMAL</state>
+        <guest osCustomization="true">
+            <operatingSystem id="REDHAT664" displayName="REDHAT6/64" family="UNIX"/>
+            <vmTools type="vmx-08" versionStatus="NEED_UPGRADE" runningStatus="NOT_RUNNING" apiVersion="8389"/>
+        </guest>
+</customerImage>

http://git-wip-us.apache.org/repos/asf/libcloud/blob/03a2aa4e/libcloud/test/compute/fixtures/dimensiondata/image_osImage.xml
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/dimensiondata/image_osImage.xml b/libcloud/test/compute/fixtures/dimensiondata/image_osImage.xml
index 1f884a9..4af7e09 100644
--- a/libcloud/test/compute/fixtures/dimensiondata/image_osImage.xml
+++ b/libcloud/test/compute/fixtures/dimensiondata/image_osImage.xml
@@ -3,32 +3,41 @@
     <osImage id="c14b1a46-2428-44c1-9c1a-b20e6418d08c" datacenterId="NA9">
         <name>RedHat 6 64-bit 2 CPU</name>
         <description>RedHat 6.6 Enterprise (Santiago) 64-bit</description>
-        <operatingSystem id="REDHAT664" displayName="REDHAT6/64" family="UNIX" />
-        <cpu count="2" speed="STANDARD" coresPerSocket="1" />
+        <cpu count="2" speed="STANDARD" coresPerSocket="1"/>
         <memoryGb>4</memoryGb>
-        <disk id="a02b7244-99d8-4889-84a5-5e4373c1bb26" scsiId="0" sizeGb="10" speed="STANDARD" />
-        <createTime>2015-09-17T11:23:48.000Z</createTime>
+        <disk id="5f709ffe-ae38-4d3b-8aeb-57cbc5036627" scsiId="0" sizeGb="10" speed="STANDARD"/>
+        <createTime>2015-09-23T10:17:28.000Z</createTime>
         <osImageKey>T-RHEL-6-64-2-4-10</osImageKey>
+        <sortOrder>0</sortOrder>
+        <guest osCustomization="true">
+            <operatingSystem id="REDHAT664" displayName="REDHAT6/64" family="UNIX"/>
+        </guest>
     </osImage>
     <osImage id="6b4fb0c7-a57b-4f58-b59c-9958f94f971a" datacenterId="NA9">
         <name>Win2012 DC 2 CPU</name>
         <description>Windows 2012 Datacenter</description>
-        <operatingSystem id="WIN2012DC64" displayName="WIN2012DC/64" family="WINDOWS" />
-        <cpu count="2" speed="STANDARD" coresPerSocket="1" />
+        <cpu count="2" speed="STANDARD" coresPerSocket="1"/>
         <memoryGb>4</memoryGb>
-        <disk id="f5e01854-a211-4ec6-96d6-2753b6d47877" scsiId="0" sizeGb="50" speed="STANDARD" />
-        <createTime>2015-09-17T11:44:43.000Z</createTime>
+        <disk id="b74a54e6-f90a-4619-a232-4b7522cf0055" scsiId="0" sizeGb="50" speed="STANDARD"/>
+        <createTime>2015-09-23T10:19:51.000Z</createTime>
         <osImageKey>T-WIN-2012-DATACTR-64-2-4-50</osImageKey>
+        <sortOrder>0</sortOrder>
+        <guest osCustomization="true">
+            <operatingSystem id="WIN2012DC64" displayName="WIN2012DC/64" family="WINDOWS"/>
+        </guest>
     </osImage>
     <osImage id="3ebf3c0f-90fe-4a8b-8585-6e65b316592c" datacenterId="NA9">
         <name>Win2008 Std 32-bit 2 CPU</name>
         <description>Windows 2008 Enterprise R2 32-bit installed with Microsoft SQL Server 2012 Standard Edition</description>
-        <operatingSystem id="WIN2008S32" displayName="WIN2008S/32" family="WINDOWS" />
-        <cpu count="2" speed="STANDARD" coresPerSocket="1" />
+        <cluster id="QA1_N2_VMWARE_1-01" name="QA1_N2_VMWARE_1-01"/>
+        <cpu count="2" speed="STANDARD" coresPerSocket="1"/>
         <memoryGb>4</memoryGb>
-        <disk id="6e5b5112-0eae-44eb-83cd-1bd0d58fbeab" scsiId="0" sizeGb="50" speed="STANDARD" />
-        <softwareLabel>MSSQL2008R2S</softwareLabel>
-        <createTime>2014-11-20T12:54:22.000Z</createTime>
+        <disk id="3ee8ecd1-cae6-4bb3-81b2-1294b7763d24" scsiId="0" sizeGb="50" speed="STANDARD"/>
+        <createTime>2015-06-16T14:22:41.000Z</createTime>
         <osImageKey>T-WIN-2008-ENT-32-2-4-50</osImageKey>
+        <sortOrder>0</sortOrder>
+        <guest osCustomization="true">
+            <operatingSystem id="WIN2008S32" displayName="WIN2008S/32" family="WINDOWS"/>
+        </guest>
     </osImage>
 </osImages>

http://git-wip-us.apache.org/repos/asf/libcloud/blob/03a2aa4e/libcloud/test/compute/fixtures/dimensiondata/image_osImage_6b4fb0c7_a57b_4f58_b59c_9958f94f971a.xml
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/dimensiondata/image_osImage_6b4fb0c7_a57b_4f58_b59c_9958f94f971a.xml b/libcloud/test/compute/fixtures/dimensiondata/image_osImage_6b4fb0c7_a57b_4f58_b59c_9958f94f971a.xml
index 1631137..a2ea8cb 100644
--- a/libcloud/test/compute/fixtures/dimensiondata/image_osImage_6b4fb0c7_a57b_4f58_b59c_9958f94f971a.xml
+++ b/libcloud/test/compute/fixtures/dimensiondata/image_osImage_6b4fb0c7_a57b_4f58_b59c_9958f94f971a.xml
@@ -1,11 +1,14 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes"?>
-  <osImage xmlns="urn:didata.com:api:cloud:types" id="6b4fb0c7-a57b-4f58-b59c-9958f94f971a" datacenterId="NA9">
+<osImage xmlns="urn:didata.com:api:cloud:types" id="6b4fb0c7-a57b-4f58-b59c-9958f94f971a" datacenterId="NA9">
     <name>Win2012 DC 2 CPU</name>
     <description>Windows 2012 Datacenter</description>
-    <operatingSystem id="WIN2012DC64" displayName="WIN2012DC/64" family="WINDOWS" />
-    <cpu count="2" speed="STANDARD" coresPerSocket="1" />
-    <memoryGb>4</memoryGb>
-    <disk id="f5e01854-a211-4ec6-96d6-2753b6d47877" scsiId="0" sizeGb="50" speed="STANDARD" />
-    <createTime>2015-09-17T11:44:43.000Z</createTime>
-    <osImageKey>T-WIN-2012-DATACTR-64-2-4-50</osImageKey>
-  </osImage>
+        <cpu count="2" speed="STANDARD" coresPerSocket="1"/>
+        <memoryGb>4</memoryGb>
+        <disk id="b74a54e6-f90a-4619-a232-4b7522cf0055" scsiId="0" sizeGb="50" speed="STANDARD"/>
+        <createTime>2015-09-23T10:19:51.000Z</createTime>
+        <osImageKey>T-WIN-2012-DATACTR-64-2-4-50</osImageKey>
+        <sortOrder>0</sortOrder>
+        <guest osCustomization="true">
+            <operatingSystem id="WIN2012DC64" displayName="WIN2012DC/64" family="WINDOWS"/>
+        </guest>
+</osImage>

http://git-wip-us.apache.org/repos/asf/libcloud/blob/03a2aa4e/libcloud/test/compute/fixtures/dimensiondata/image_osImage_c14b1a46_2428_44c1_9c1a_b20e6418d08c.xml
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/dimensiondata/image_osImage_c14b1a46_2428_44c1_9c1a_b20e6418d08c.xml b/libcloud/test/compute/fixtures/dimensiondata/image_osImage_c14b1a46_2428_44c1_9c1a_b20e6418d08c.xml
index 27d6c25..62fa6b0 100644
--- a/libcloud/test/compute/fixtures/dimensiondata/image_osImage_c14b1a46_2428_44c1_9c1a_b20e6418d08c.xml
+++ b/libcloud/test/compute/fixtures/dimensiondata/image_osImage_c14b1a46_2428_44c1_9c1a_b20e6418d08c.xml
@@ -1,12 +1,17 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-  <osImage xmlns="urn:didata.com:api:cloud:types" id="c14b1a46-2428-44c1-9c1a-b20e6418d08c" datacenterId="NA9">
+<?xml version="1.0" encoding="UTF-8"?>
+<osImage xmlns="urn:didata.com:api:cloud:types"
+         id="c14b1a46-2428-44c1-9c1a-b20e6418d08c" datacenterId="NA9">
     <name>RedHat 6 64-bit 2 CPU</name>
     <description>RedHat 6.6 Enterprise (Santiago) 64-bit</description>
-    <operatingSystem id="REDHAT664" displayName="REDHAT6/64" family="UNIX" />
     <cpu count="2" speed="STANDARD" coresPerSocket="1" />
     <memoryGb>4</memoryGb>
-    <disk id="a02b7244-99d8-4889-84a5-5e4373c1bb26" scsiId="0" sizeGb="10" speed="STANDARD" />
-    <createTime>2015-09-17T11:23:48.000Z</createTime>
+    <disk id="5f709ffe-ae38-4d3b-8aeb-57cbc5036627" scsiId="0" sizeGb="10"
+          speed="STANDARD" />
+    <createTime>2015-09-23T10:17:28.000Z</createTime>
     <osImageKey>T-RHEL-6-64-2-4-10</osImageKey>
-  </osImage>
-
+    <sortOrder>0</sortOrder>
+    <guest osCustomization="true">
+        <operatingSystem id="REDHAT664" displayName="REDHAT6/64"
+                         family="UNIX" />
+    </guest>
+</osImage>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/libcloud/blob/03a2aa4e/libcloud/test/compute/test_dimensiondata.py
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/test_dimensiondata.py b/libcloud/test/compute/test_dimensiondata.py
index 563448a..bf121b5 100644
--- a/libcloud/test/compute/test_dimensiondata.py
+++ b/libcloud/test/compute/test_dimensiondata.py
@@ -136,7 +136,7 @@ class DimensionDataTests(unittest.TestCase, TestCaseMixin):
         self.assertTrue(isinstance(node_list_generator, GeneratorType))
 
     # We're making sure here the filters make it to the URL
-    # See  _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_server_ALLFILTERS for asserts
+    # See  _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_server_ALLFILTERS for asserts
     def test_list_nodes_response_strings_ALLFILTERS(self):
         DimensionDataMockHttp.type = 'ALLFILTERS'
         ret = self.driver.list_nodes(ex_location='fake_loc', ex_name='fake_name',
@@ -1622,11 +1622,11 @@ class DimensionDataTests(unittest.TestCase, TestCaseMixin):
             self.driver._location_to_location_id([1, 2, 3])
 
     def test_priv_image_needs_auth_os_img(self):
-        image = self.driver.list_images()[0]
+        image = self.driver.list_images()[1]
         self.assertTrue(self.driver._image_needs_auth(image))
 
     def test_priv_image_needs_auth_os_img_STR(self):
-        image = self.driver.list_images()[0].id
+        image = self.driver.list_images()[1].id
         self.assertTrue(self.driver._image_needs_auth(image))
 
     def test_priv_image_needs_auth_cust_img_windows(self):
@@ -2221,12 +2221,12 @@ class DimensionDataMockHttp(StorageMockHttp, MockHttp):
         )
         return (httplib.BAD_REQUEST, body, {}, httplib.responses[httplib.OK])
 
-    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server(self, method, url, body, headers):
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server(self, method, url, body, headers):
         body = self.fixtures.load(
             'server.xml')
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
-    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_deleteServer(self, method, url, body, headers):
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_deleteServer(self, method, url, body, headers):
         request = ET.fromstring(body)
         if request.tag != "{urn:didata.com:api:cloud:types}deleteServer":
             raise InvalidRequestError(request.tag)
@@ -2234,7 +2234,7 @@ class DimensionDataMockHttp(StorageMockHttp, MockHttp):
             'server_deleteServer.xml')
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
-    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_deleteServer_INPROGRESS(self, method, url, body, headers):
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_deleteServer_INPROGRESS(self, method, url, body, headers):
         request = ET.fromstring(body)
         if request.tag != "{urn:didata.com:api:cloud:types}deleteServer":
             raise InvalidRequestError(request.tag)
@@ -2242,7 +2242,7 @@ class DimensionDataMockHttp(StorageMockHttp, MockHttp):
             'server_deleteServer_RESOURCEBUSY.xml')
         return (httplib.BAD_REQUEST, body, {}, httplib.responses[httplib.OK])
 
-    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_rebootServer(self, method, url, body, headers):
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_rebootServer(self, method, url, body, headers):
         request = ET.fromstring(body)
         if request.tag != "{urn:didata.com:api:cloud:types}rebootServer":
             raise InvalidRequestError(request.tag)
@@ -2250,7 +2250,7 @@ class DimensionDataMockHttp(StorageMockHttp, MockHttp):
             'server_rebootServer.xml')
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
-    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_rebootServer_INPROGRESS(self, method, url, body, headers):
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_rebootServer_INPROGRESS(self, method, url, body, headers):
         request = ET.fromstring(body)
         if request.tag != "{urn:didata.com:api:cloud:types}rebootServer":
             raise InvalidRequestError(request.tag)
@@ -2258,7 +2258,7 @@ class DimensionDataMockHttp(StorageMockHttp, MockHttp):
             'server_rebootServer_RESOURCEBUSY.xml')
         return (httplib.BAD_REQUEST, body, {}, httplib.responses[httplib.OK])
 
-    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_server(self, method, url, body, headers):
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_server(self, method, url, body, headers):
         if url.endswith('datacenterId=NA3'):
             body = self.fixtures.load(
                 'server_server_NA3.xml')
@@ -2268,19 +2268,19 @@ class DimensionDataMockHttp(StorageMockHttp, MockHttp):
             'server_server.xml')
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
-    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_server_PAGESIZE50(self, method, url, body, headers):
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_server_PAGESIZE50(self, method, url, body, headers):
         if not url.endswith('pageSize=50'):
             raise ValueError("pageSize is not set as expected")
         body = self.fixtures.load(
             'server_server.xml')
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
-    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_server_EMPTY(self, method, url, body, headers):
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_server_EMPTY(self, method, url, body, headers):
         body = self.fixtures.load(
             'server_server_paginated_empty.xml')
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
-    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_server_PAGED_THEN_EMPTY(self, method, url, body, headers):
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_server_PAGED_THEN_EMPTY(self, method, url, body, headers):
         if 'pageNumber=2' in url:
             body = self.fixtures.load(
                 'server_server_paginated_empty.xml')
@@ -2290,7 +2290,7 @@ class DimensionDataMockHttp(StorageMockHttp, MockHttp):
                 'server_server_paginated.xml')
             return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
-    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_server_PAGINATED(self, method, url, body, headers):
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_server_PAGINATED(self, method, url, body, headers):
         if 'pageNumber=2' in url:
             body = self.fixtures.load(
                 'server_server.xml')
@@ -2300,12 +2300,12 @@ class DimensionDataMockHttp(StorageMockHttp, MockHttp):
                 'server_server_paginated.xml')
             return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
-    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_server_PAGINATEDEMPTY(self, method, url, body, headers):
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_server_PAGINATEDEMPTY(self, method, url, body, headers):
         body = self.fixtures.load(
             'server_server_paginated_empty.xml')
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
-    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_server_ALLFILTERS(self, method, url, body, headers):
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_server_ALLFILTERS(self, method, url, body, headers):
         (_, params) = url.split('?')
         parameters = params.split('&')
         for parameter in parameters:
@@ -2338,13 +2338,13 @@ class DimensionDataMockHttp(StorageMockHttp, MockHttp):
             'server_server.xml')
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
-    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_antiAffinityRule(self, method, url, body, headers):
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_antiAffinityRule(self, method, url, body, headers):
         body = self.fixtures.load(
             'server_antiAffinityRule_list.xml'
         )
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
-    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_antiAffinityRule_ALLFILTERS(self, method, url, body, headers):
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_antiAffinityRule_ALLFILTERS(self, method, url, body, headers):
         (_, params) = url.split('?')
         parameters = params.split('&')
         for parameter in parameters:
@@ -2364,7 +2364,7 @@ class DimensionDataMockHttp(StorageMockHttp, MockHttp):
         )
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
-    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_antiAffinityRule_PAGINATED(self, method, url, body, headers):
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_antiAffinityRule_PAGINATED(self, method, url, body, headers):
         if 'pageNumber=2' in url:
             body = self.fixtures.load(
                 'server_antiAffinityRule_list.xml')
@@ -2374,7 +2374,7 @@ class DimensionDataMockHttp(StorageMockHttp, MockHttp):
                 'server_antiAffinityRule_list_PAGINATED.xml')
             return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
-    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_infrastructure_datacenter(self, method, url, body, headers):
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_infrastructure_datacenter(self, method, url, body, headers):
         if url.endswith('id=NA9'):
             body = self.fixtures.load(
                 'infrastructure_datacenter_NA9.xml')
@@ -2384,7 +2384,7 @@ class DimensionDataMockHttp(StorageMockHttp, MockHttp):
             'infrastructure_datacenter.xml')
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
-    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_infrastructure_datacenter_ALLFILTERS(self, method, url, body, headers):
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_infrastructure_datacenter_ALLFILTERS(self, method, url, body, headers):
         if url.endswith('id=NA9'):
             body = self.fixtures.load(
                 'infrastructure_datacenter_NA9.xml')
@@ -2394,7 +2394,7 @@ class DimensionDataMockHttp(StorageMockHttp, MockHttp):
             'infrastructure_datacenter.xml')
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
-    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_updateVmwareTools(self, method, url, body, headers):
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_updateVmwareTools(self, method, url, body, headers):
         request = ET.fromstring(body)
         if request.tag != "{urn:didata.com:api:cloud:types}updateVmwareTools":
             raise InvalidRequestError(request.tag)
@@ -2402,7 +2402,7 @@ class DimensionDataMockHttp(StorageMockHttp, MockHttp):
             'server_updateVmwareTools.xml')
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
-    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_startServer(self, method, url, body, headers):
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_startServer(self, method, url, body, headers):
         request = ET.fromstring(body)
         if request.tag != "{urn:didata.com:api:cloud:types}startServer":
             raise InvalidRequestError(request.tag)
@@ -2410,7 +2410,7 @@ class DimensionDataMockHttp(StorageMockHttp, MockHttp):
             'server_startServer.xml')
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
-    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_startServer_INPROGRESS(self, method, url, body, headers):
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_startServer_INPROGRESS(self, method, url, body, headers):
         request = ET.fromstring(body)
         if request.tag != "{urn:didata.com:api:cloud:types}startServer":
             raise InvalidRequestError(request.tag)
@@ -2418,7 +2418,7 @@ class DimensionDataMockHttp(StorageMockHttp, MockHttp):
             'server_startServer_INPROGRESS.xml')
         return (httplib.BAD_REQUEST, body, {}, httplib.responses[httplib.OK])
 
-    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_shutdownServer(self, method, url, body, headers):
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_shutdownServer(self, method, url, body, headers):
         request = ET.fromstring(body)
         if request.tag != "{urn:didata.com:api:cloud:types}shutdownServer":
             raise InvalidRequestError(request.tag)
@@ -2426,7 +2426,7 @@ class DimensionDataMockHttp(StorageMockHttp, MockHttp):
             'server_shutdownServer.xml')
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
-    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_shutdownServer_INPROGRESS(self, method, url, body, headers):
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_shutdownServer_INPROGRESS(self, method, url, body, headers):
         request = ET.fromstring(body)
         if request.tag != "{urn:didata.com:api:cloud:types}shutdownServer":
             raise InvalidRequestError(request.tag)
@@ -2434,7 +2434,7 @@ class DimensionDataMockHttp(StorageMockHttp, MockHttp):
             'server_shutdownServer_INPROGRESS.xml')
         return (httplib.BAD_REQUEST, body, {}, httplib.responses[httplib.OK])
 
-    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_resetServer(self, method, url, body, headers):
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_resetServer(self, method, url, body, headers):
         request = ET.fromstring(body)
         if request.tag != "{urn:didata.com:api:cloud:types}resetServer":
             raise InvalidRequestError(request.tag)
@@ -2442,7 +2442,7 @@ class DimensionDataMockHttp(StorageMockHttp, MockHttp):
             'server_resetServer.xml')
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
-    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_powerOffServer(self, method, url, body, headers):
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_powerOffServer(self, method, url, body, headers):
         request = ET.fromstring(body)
         if request.tag != "{urn:didata.com:api:cloud:types}powerOffServer":
             raise InvalidRequestError(request.tag)
@@ -2450,7 +2450,7 @@ class DimensionDataMockHttp(StorageMockHttp, MockHttp):
             'server_powerOffServer.xml')
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
-    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_powerOffServer_INPROGRESS(self, method, url, body, headers):
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_powerOffServer_INPROGRESS(self, method, url, body, headers):
         request = ET.fromstring(body)
         if request.tag != "{urn:didata.com:api:cloud:types}powerOffServer":
             raise InvalidRequestError(request.tag)
@@ -2458,17 +2458,17 @@ class DimensionDataMockHttp(StorageMockHttp, MockHttp):
             'server_powerOffServer_INPROGRESS.xml')
         return (httplib.BAD_REQUEST, body, {}, httplib.responses[httplib.OK])
 
-    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_server_11_INPROGRESS(
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_server_11_INPROGRESS(
             self, method, url, body, headers):
         body = self.fixtures.load('server_GetServer.xml')
         return (httplib.BAD_REQUEST, body, {}, httplib.responses[httplib.OK])
 
-    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_networkDomain(self, method, url, body, headers):
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_networkDomain(self, method, url, body, headers):
         body = self.fixtures.load(
             'network_networkDomain.xml')
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
-    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_networkDomain_ALLFILTERS(self, method, url, body, headers):
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_networkDomain_ALLFILTERS(self, method, url, body, headers):
         (_, params) = url.split('?')
         parameters = params.split('&')
         for parameter in parameters:
@@ -2487,12 +2487,12 @@ class DimensionDataMockHttp(StorageMockHttp, MockHttp):
             'network_networkDomain.xml')
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
-    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_vlan(self, method, url, body, headers):
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_vlan(self, method, url, body, headers):
         body = self.fixtures.load(
             'network_vlan.xml')
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
-    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_vlan_ALLFILTERS(self, method, url, body, headers):
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_vlan_ALLFILTERS(self, method, url, body, headers):
         (_, params) = url.split('?')
         parameters = params.split('&')
         for parameter in parameters:
@@ -2515,7 +2515,7 @@ class DimensionDataMockHttp(StorageMockHttp, MockHttp):
             'network_vlan.xml')
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
-    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_deployServer(self, method, url, body, headers):
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_deployServer(self, method, url, body, headers):
         request = ET.fromstring(body)
         if request.tag != "{urn:didata.com:api:cloud:types}deployServer":
             raise InvalidRequestError(request.tag)
@@ -2546,12 +2546,12 @@ class DimensionDataMockHttp(StorageMockHttp, MockHttp):
             'server_deployServer.xml')
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
-    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_server_e75ead52_692f_4314_8725_c8a4f4d13a87(self, method, url, body, headers):
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_server_e75ead52_692f_4314_8725_c8a4f4d13a87(self, method, url, body, headers):
         body = self.fixtures.load(
             'server_server_e75ead52_692f_4314_8725_c8a4f4d13a87.xml')
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
-    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_deployNetworkDomain(self, method, url, body, headers):
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_deployNetworkDomain(self, method, url, body, headers):
         request = ET.fromstring(body)
         if request.tag != "{urn:didata.com:api:cloud:types}deployNetworkDomain":
             raise InvalidRequestError(request.tag)
@@ -2559,17 +2559,17 @@ class DimensionDataMockHttp(StorageMockHttp, MockHttp):
             'network_deployNetworkDomain.xml')
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
-    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_networkDomain_8cdfd607_f429_4df6_9352_162cfc0891be(self, method, url, body, headers):
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_networkDomain_8cdfd607_f429_4df6_9352_162cfc0891be(self, method, url, body, headers):
         body = self.fixtures.load(
             'network_networkDomain_8cdfd607_f429_4df6_9352_162cfc0891be.xml')
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
-    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_networkDomain_8cdfd607_f429_4df6_9352_162cfc0891be_ALLFILTERS(self, method, url, body, headers):
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_networkDomain_8cdfd607_f429_4df6_9352_162cfc0891be_ALLFILTERS(self, method, url, body, headers):
         body = self.fixtures.load(
             'network_networkDomain_8cdfd607_f429_4df6_9352_162cfc0891be.xml')
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
-    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_editNetworkDomain(self, method, url, body, headers):
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_editNetworkDomain(self, method, url, body, headers):
         request = ET.fromstring(body)
         if request.tag != "{urn:didata.com:api:cloud:types}editNetworkDomain":
             raise InvalidRequestError(request.tag)
@@ -2577,7 +2577,7 @@ class DimensionDataMockHttp(StorageMockHttp, MockHttp):
             'network_editNetworkDomain.xml')
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
-    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_deleteNetworkDomain(self, method, url, body, headers):
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_deleteNetworkDomain(self, method, url, body, headers):
         request = ET.fromstring(body)
         if request.tag != "{urn:didata.com:api:cloud:types}deleteNetworkDomain":
             raise InvalidRequestError(request.tag)
@@ -2585,7 +2585,7 @@ class DimensionDataMockHttp(StorageMockHttp, MockHttp):
             'network_deleteNetworkDomain.xml')
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
-    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_deployVlan(self, method, url, body, headers):
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_deployVlan(self, method, url, body, headers):
         request = ET.fromstring(body)
         if request.tag != "{urn:didata.com:api:cloud:types}deployVlan":
             raise InvalidRequestError(request.tag)
@@ -2593,12 +2593,12 @@ class DimensionDataMockHttp(StorageMockHttp, MockHttp):
             'network_deployVlan.xml')
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
-    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_vlan_0e56433f_d808_4669_821d_812769517ff8(self, method, url, body, headers):
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_vlan_0e56433f_d808_4669_821d_812769517ff8(self, method, url, body, headers):
         body = self.fixtures.load(
             'network_vlan_0e56433f_d808_4669_821d_812769517ff8.xml')
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
-    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_editVlan(self, method, url, body, headers):
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_editVlan(self, method, url, body, headers):
         request = ET.fromstring(body)
         if request.tag != "{urn:didata.com:api:cloud:types}editVlan":
             raise InvalidRequestError(request.tag)
@@ -2606,7 +2606,7 @@ class DimensionDataMockHttp(StorageMockHttp, MockHttp):
             'network_editVlan.xml')
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
-    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_deleteVlan(self, method, url, body, headers):
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_deleteVlan(self, method, url, body, headers):
         request = ET.fromstring(body)
         if request.tag != "{urn:didata.com:api:cloud:types}deleteVlan":
             raise InvalidRequestError(request.tag)
@@ -2614,7 +2614,7 @@ class DimensionDataMockHttp(StorageMockHttp, MockHttp):
             'network_deleteVlan.xml')
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
-    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_expandVlan(self, method, url, body, headers):
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_expandVlan(self, method, url, body, headers):
         request = ET.fromstring(body)
         if request.tag != "{urn:didata.com:api:cloud:types}expandVlan":
             raise InvalidRequestError(request.tag)
@@ -2622,7 +2622,7 @@ class DimensionDataMockHttp(StorageMockHttp, MockHttp):
             'network_expandVlan.xml')
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
-    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_addPublicIpBlock(self, method, url, body, headers):
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_addPublicIpBlock(self, method, url, body, headers):
         request = ET.fromstring(body)
         if request.tag != "{urn:didata.com:api:cloud:types}addPublicIpBlock":
             raise InvalidRequestError(request.tag)
@@ -2630,22 +2630,22 @@ class DimensionDataMockHttp(StorageMockHttp, MockHttp):
             'network_addPublicIpBlock.xml')
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
-    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_publicIpBlock_4487241a_f0ca_11e3_9315_d4bed9b167ba(self, method, url, body, headers):
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_publicIpBlock_4487241a_f0ca_11e3_9315_d4bed9b167ba(self, method, url, body, headers):
         body = self.fixtures.load(
             'network_publicIpBlock_4487241a_f0ca_11e3_9315_d4bed9b167ba.xml')
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
-    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_publicIpBlock(self, method, url, body, headers):
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_publicIpBlock(self, method, url, body, headers):
         body = self.fixtures.load(
             'network_publicIpBlock.xml')
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
-    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_publicIpBlock_9945dc4a_bdce_11e4_8c14_b8ca3a5d9ef8(self, method, url, body, headers):
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_publicIpBlock_9945dc4a_bdce_11e4_8c14_b8ca3a5d9ef8(self, method, url, body, headers):
         body = self.fixtures.load(
             'network_publicIpBlock_9945dc4a_bdce_11e4_8c14_b8ca3a5d9ef8.xml')
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
-    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_removePublicIpBlock(self, method, url, body, headers):
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_removePublicIpBlock(self, method, url, body, headers):
         request = ET.fromstring(body)
         if request.tag != "{urn:didata.com:api:cloud:types}removePublicIpBlock":
             raise InvalidRequestError(request.tag)
@@ -2653,12 +2653,12 @@ class DimensionDataMockHttp(StorageMockHttp, MockHttp):
             'network_removePublicIpBlock.xml')
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
-    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_firewallRule(self, method, url, body, headers):
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_firewallRule(self, method, url, body, headers):
         body = self.fixtures.load(
             'network_firewallRule.xml')
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
-    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_createFirewallRule(self, method, url, body, headers):
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_createFirewallRule(self, method, url, body, headers):
         request = ET.fromstring(body)
         if request.tag != "{urn:didata.com:api:cloud:types}createFirewallRule":
             raise InvalidRequestError(request.tag)
@@ -2666,12 +2666,12 @@ class DimensionDataMockHttp(StorageMockHttp, MockHttp):
             'network_createFirewallRule.xml')
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
-    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_firewallRule_d0a20f59_77b9_4f28_a63b_e58496b73a6c(self, method, url, body, headers):
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_firewallRule_d0a20f59_77b9_4f28_a63b_e58496b73a6c(self, method, url, body, headers):
         body = self.fixtures.load(
             'network_firewallRule_d0a20f59_77b9_4f28_a63b_e58496b73a6c.xml')
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
-    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_editFirewallRule(self, method, url, body, headers):
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_editFirewallRule(self, method, url, body, headers):
         request = ET.fromstring(body)
         if request.tag != "{urn:didata.com:api:cloud:types}editFirewallRule":
             raise InvalidRequestError(request.tag)
@@ -2679,7 +2679,7 @@ class DimensionDataMockHttp(StorageMockHttp, MockHttp):
             'network_editFirewallRule.xml')
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
-    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_deleteFirewallRule(self, method, url, body, headers):
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_deleteFirewallRule(self, method, url, body, headers):
         request = ET.fromstring(body)
         if request.tag != "{urn:didata.com:api:cloud:types}deleteFirewallRule":
             raise InvalidRequestError(request.tag)
@@ -2687,7 +2687,7 @@ class DimensionDataMockHttp(StorageMockHttp, MockHttp):
             'network_deleteFirewallRule.xml')
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
-    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_createNatRule(self, method, url, body, headers):
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_createNatRule(self, method, url, body, headers):
         request = ET.fromstring(body)
         if request.tag != "{urn:didata.com:api:cloud:types}createNatRule":
             raise InvalidRequestError(request.tag)
@@ -2695,17 +2695,17 @@ class DimensionDataMockHttp(StorageMockHttp, MockHttp):
             'network_createNatRule.xml')
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
-    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_natRule(self, method, url, body, headers):
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_natRule(self, method, url, body, headers):
         body = self.fixtures.load(
             'network_natRule.xml')
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
-    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_natRule_2187a636_7ebb_49a1_a2ff_5d617f496dce(self, method, url, body, headers):
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_natRule_2187a636_7ebb_49a1_a2ff_5d617f496dce(self, method, url, body, headers):
         body = self.fixtures.load(
             'network_natRule_2187a636_7ebb_49a1_a2ff_5d617f496dce.xml')
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
-    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_deleteNatRule(self, method, url, body, headers):
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_deleteNatRule(self, method, url, body, headers):
         request = ET.fromstring(body)
         if request.tag != "{urn:didata.com:api:cloud:types}deleteNatRule":
             raise InvalidRequestError(request.tag)
@@ -2713,7 +2713,7 @@ class DimensionDataMockHttp(StorageMockHttp, MockHttp):
             'network_deleteNatRule.xml')
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
-    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_addNic(self, method, url, body, headers):
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_addNic(self, method, url, body, headers):
         request = ET.fromstring(body)
         if request.tag != "{urn:didata.com:api:cloud:types}addNic":
             raise InvalidRequestError(request.tag)
@@ -2721,7 +2721,7 @@ class DimensionDataMockHttp(StorageMockHttp, MockHttp):
             'server_addNic.xml')
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
-    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_removeNic(self, method, url, body, headers):
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_removeNic(self, method, url, body, headers):
         request = ET.fromstring(body)
         if request.tag != "{urn:didata.com:api:cloud:types}removeNic":
             raise InvalidRequestError(request.tag)
@@ -2729,7 +2729,7 @@ class DimensionDataMockHttp(StorageMockHttp, MockHttp):
             'server_removeNic.xml')
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
-    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_disableServerMonitoring(self, method, url, body, headers):
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_disableServerMonitoring(self, method, url, body, headers):
         request = ET.fromstring(body)
         if request.tag != "{urn:didata.com:api:cloud:types}disableServerMonitoring":
             raise InvalidRequestError(request.tag)
@@ -2737,7 +2737,7 @@ class DimensionDataMockHttp(StorageMockHttp, MockHttp):
             'server_disableServerMonitoring.xml')
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
-    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_enableServerMonitoring(self, method, url, body, headers):
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_enableServerMonitoring(self, method, url, body, headers):
         request = ET.fromstring(body)
         if request.tag != "{urn:didata.com:api:cloud:types}enableServerMonitoring":
             raise InvalidRequestError(request.tag)
@@ -2745,7 +2745,7 @@ class DimensionDataMockHttp(StorageMockHttp, MockHttp):
             'server_enableServerMonitoring.xml')
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
-    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_changeServerMonitoringPlan(self, method, url, body, headers):
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_changeServerMonitoringPlan(self, method, url, body, headers):
         request = ET.fromstring(body)
         if request.tag != "{urn:didata.com:api:cloud:types}changeServerMonitoringPlan":
             raise InvalidRequestError(request.tag)
@@ -2753,57 +2753,57 @@ class DimensionDataMockHttp(StorageMockHttp, MockHttp):
             'server_changeServerMonitoringPlan.xml')
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
-    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_image_osImage(self, method, url, body, headers):
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_image_osImage(self, method, url, body, headers):
         body = self.fixtures.load(
             'image_osImage.xml')
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
-    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_image_osImage_c14b1a46_2428_44c1_9c1a_b20e6418d08c(self, method, url, body, headers):
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_image_osImage_c14b1a46_2428_44c1_9c1a_b20e6418d08c(self, method, url, body, headers):
         body = self.fixtures.load(
             'image_osImage_c14b1a46_2428_44c1_9c1a_b20e6418d08c.xml')
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
-    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_image_osImage_6b4fb0c7_a57b_4f58_b59c_9958f94f971a(self, method, url, body, headers):
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_image_osImage_6b4fb0c7_a57b_4f58_b59c_9958f94f971a(self, method, url, body, headers):
         body = self.fixtures.load(
             'image_osImage_6b4fb0c7_a57b_4f58_b59c_9958f94f971a.xml')
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
-    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_image_osImage_5234e5c7_01de_4411_8b6e_baeb8d91cf5d(self, method, url, body, headers):
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_image_osImage_5234e5c7_01de_4411_8b6e_baeb8d91cf5d(self, method, url, body, headers):
         body = self.fixtures.load(
             'image_osImage_BAD_REQUEST.xml')
         return (httplib.BAD_REQUEST, body, {}, httplib.responses[httplib.OK])
 
-    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_image_osImage_2ffa36c8_1848_49eb_b4fa_9d908775f68c(self, method, url, body, headers):
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_image_osImage_2ffa36c8_1848_49eb_b4fa_9d908775f68c(self, method, url, body, headers):
         body = self.fixtures.load(
             'image_osImage_BAD_REQUEST.xml')
         return (httplib.BAD_REQUEST, body, {}, httplib.responses[httplib.OK])
 
-    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_image_osImage_FAKE_IMAGE_ID(self, method, url, body, headers):
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_image_osImage_FAKE_IMAGE_ID(self, method, url, body, headers):
         body = self.fixtures.load(
             'image_osImage_BAD_REQUEST.xml')
         return (httplib.BAD_REQUEST, body, {}, httplib.responses[httplib.OK])
 
-    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_image_customerImage(self, method, url, body, headers):
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_image_customerImage(self, method, url, body, headers):
         body = self.fixtures.load(
             'image_customerImage.xml')
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
-    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_image_customerImage_5234e5c7_01de_4411_8b6e_baeb8d91cf5d(self, method, url, body, headers):
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_image_customerImage_5234e5c7_01de_4411_8b6e_baeb8d91cf5d(self, method, url, body, headers):
         body = self.fixtures.load(
             'image_customerImage_5234e5c7_01de_4411_8b6e_baeb8d91cf5d.xml')
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
-    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_image_customerImage_2ffa36c8_1848_49eb_b4fa_9d908775f68c(self, method, url, body, headers):
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_image_customerImage_2ffa36c8_1848_49eb_b4fa_9d908775f68c(self, method, url, body, headers):
         body = self.fixtures.load(
             'image_customerImage_2ffa36c8_1848_49eb_b4fa_9d908775f68c.xml')
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
-    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_image_customerImage_FAKE_IMAGE_ID(self, method, url, body, headers):
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_image_customerImage_FAKE_IMAGE_ID(self, method, url, body, headers):
         body = self.fixtures.load(
             'image_customerImage_BAD_REQUEST.xml')
         return (httplib.BAD_REQUEST, body, {}, httplib.responses[httplib.OK])
 
-    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_reconfigureServer(self, method, url, body, headers):
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_reconfigureServer(self, method, url, body, headers):
         request = ET.fromstring(body)
         if request.tag != "{urn:didata.com:api:cloud:types}reconfigureServer":
             raise InvalidRequestError(request.tag)
@@ -2811,22 +2811,22 @@ class DimensionDataMockHttp(StorageMockHttp, MockHttp):
             'server_reconfigureServer.xml')
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
-    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_cleanServer(self, method, url, body, headers):
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_cleanServer(self, method, url, body, headers):
         body = self.fixtures.load(
             'server_cleanServer.xml')
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
-    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_addDisk(self, method, url, body, headers):
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_addDisk(self, method, url, body, headers):
         body = self.fixtures.load(
             'server_addDisk.xml')
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
-    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_removeDisk(self, method, url, body, headers):
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_removeDisk(self, method, url, body, headers):
         body = self.fixtures.load(
             'server_removeDisk.xml')
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
-    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_tag_createTagKey(self, method, url, body, headers):
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_tag_createTagKey(self, method, url, body, headers):
         request = ET.fromstring(body)
         if request.tag != "{urn:didata.com:api:cloud:types}createTagKey":
             raise InvalidRequestError(request.tag)
@@ -2848,7 +2848,7 @@ class DimensionDataMockHttp(StorageMockHttp, MockHttp):
         )
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
-    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_tag_createTagKey_ALLPARAMS(self, method, url, body, headers):
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_tag_createTagKey_ALLPARAMS(self, method, url, body, headers):
         request = ET.fromstring(body)
         if request.tag != "{urn:didata.com:api:cloud:types}createTagKey":
             raise InvalidRequestError(request.tag)
@@ -2870,24 +2870,24 @@ class DimensionDataMockHttp(StorageMockHttp, MockHttp):
         )
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
-    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_tag_createTagKey_BADREQUEST(self, method, url, body, headers):
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_tag_createTagKey_BADREQUEST(self, method, url, body, headers):
         body = self.fixtures.load(
             'tag_createTagKey_BADREQUEST.xml')
         return (httplib.BAD_REQUEST, body, {}, httplib.responses[httplib.OK])
 
-    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_tag_tagKey(self, method, url, body, headers):
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_tag_tagKey(self, method, url, body, headers):
         body = self.fixtures.load(
             'tag_tagKey_list.xml'
         )
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
-    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_tag_tagKey_SINGLE(self, method, url, body, headers):
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_tag_tagKey_SINGLE(self, method, url, body, headers):
         body = self.fixtures.load(
             'tag_tagKey_list_SINGLE.xml'
         )
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
-    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_tag_tagKey_ALLFILTERS(self, method, url, body, headers):
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_tag_tagKey_ALLFILTERS(self, method, url, body, headers):
         (_, params) = url.split('?')
         parameters = params.split('&')
         for parameter in parameters:
@@ -2909,19 +2909,19 @@ class DimensionDataMockHttp(StorageMockHttp, MockHttp):
         )
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
-    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_tag_tagKey_d047c609_93d7_4bc5_8fc9_732c85840075(self, method, url, body, headers):
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_tag_tagKey_d047c609_93d7_4bc5_8fc9_732c85840075(self, method, url, body, headers):
         body = self.fixtures.load(
             'tag_tagKey_5ab77f5f_5aa9_426f_8459_4eab34e03d54.xml'
         )
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
-    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_tag_tagKey_d047c609_93d7_4bc5_8fc9_732c85840075_NOEXIST(self, method, url, body, headers):
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_tag_tagKey_d047c609_93d7_4bc5_8fc9_732c85840075_NOEXIST(self, method, url, body, headers):
         body = self.fixtures.load(
             'tag_tagKey_5ab77f5f_5aa9_426f_8459_4eab34e03d54_BADREQUEST.xml'
         )
         return (httplib.BAD_REQUEST, body, {}, httplib.responses[httplib.OK])
 
-    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_tag_editTagKey_NAME(self, method, url, body, headers):
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_tag_editTagKey_NAME(self, method, url, body, headers):
         request = ET.fromstring(body)
         if request.tag != "{urn:didata.com:api:cloud:types}editTagKey":
             raise InvalidRequestError(request.tag)
@@ -2942,7 +2942,7 @@ class DimensionDataMockHttp(StorageMockHttp, MockHttp):
         )
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
-    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_tag_editTagKey_NOTNAME(self, method, url, body, headers):
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_tag_editTagKey_NOTNAME(self, method, url, body, headers):
         request = ET.fromstring(body)
         if request.tag != "{urn:didata.com:api:cloud:types}editTagKey":
             raise InvalidRequestError(request.tag)
@@ -2963,13 +2963,13 @@ class DimensionDataMockHttp(StorageMockHttp, MockHttp):
         )
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
-    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_tag_editTagKey_NOCHANGE(self, method, url, body, headers):
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_tag_editTagKey_NOCHANGE(self, method, url, body, headers):
         body = self.fixtures.load(
             'tag_editTagKey_BADREQUEST.xml'
         )
         return (httplib.BAD_REQUEST, body, {}, httplib.responses[httplib.OK])
 
-    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_tag_deleteTagKey(self, method, url, body, headers):
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_tag_deleteTagKey(self, method, url, body, headers):
         request = ET.fromstring(body)
         if request.tag != "{urn:didata.com:api:cloud:types}deleteTagKey":
             raise InvalidRequestError(request.tag)
@@ -2978,13 +2978,13 @@ class DimensionDataMockHttp(StorageMockHttp, MockHttp):
         )
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
-    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_tag_deleteTagKey_NOEXIST(self, method, url, body, headers):
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_tag_deleteTagKey_NOEXIST(self, method, url, body, headers):
         body = self.fixtures.load(
             'tag_deleteTagKey_BADREQUEST.xml'
         )
         return (httplib.BAD_REQUEST, body, {}, httplib.responses[httplib.OK])
 
-    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_tag_applyTags(self, method, url, body, headers):
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_tag_applyTags(self, method, url, body, headers):
         request = ET.fromstring(body)
         if request.tag != "{urn:didata.com:api:cloud:types}applyTags":
             raise InvalidRequestError(request.tag)
@@ -3007,7 +3007,7 @@ class DimensionDataMockHttp(StorageMockHttp, MockHttp):
         )
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
-    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_tag_applyTags_NOVALUE(self, method, url, body, headers):
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_tag_applyTags_NOVALUE(self, method, url, body, headers):
         request = ET.fromstring(body)
         if request.tag != "{urn:didata.com:api:cloud:types}applyTags":
             raise InvalidRequestError(request.tag)
@@ -3030,13 +3030,13 @@ class DimensionDataMockHttp(StorageMockHttp, MockHttp):
         )
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
-    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_tag_applyTags_NOTAGKEY(self, method, url, body, headers):
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_tag_applyTags_NOTAGKEY(self, method, url, body, headers):
         body = self.fixtures.load(
             'tag_applyTags_BADREQUEST.xml'
         )
         return (httplib.BAD_REQUEST, body, {}, httplib.responses[httplib.OK])
 
-    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_tag_removeTags(self, method, url, body, headers):
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_tag_removeTags(self, method, url, body, headers):
         request = ET.fromstring(body)
         if request.tag != "{urn:didata.com:api:cloud:types}removeTags":
             raise InvalidRequestError(request.tag)
@@ -3045,19 +3045,19 @@ class DimensionDataMockHttp(StorageMockHttp, MockHttp):
         )
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
-    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_tag_removeTags_NOTAG(self, method, url, body, headers):
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_tag_removeTags_NOTAG(self, method, url, body, headers):
         body = self.fixtures.load(
             'tag_removeTag_BADREQUEST.xml'
         )
         return (httplib.BAD_REQUEST, body, {}, httplib.responses[httplib.OK])
 
-    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_tag_tag(self, method, url, body, headers):
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_tag_tag(self, method, url, body, headers):
         body = self.fixtures.load(
             'tag_tag_list.xml'
         )
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
-    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_tag_tag_ALLPARAMS(self, method, url, body, headers):
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_tag_tag_ALLPARAMS(self, method, url, body, headers):
         (_, params) = url.split('?')
         parameters = params.split('&')
         for parameter in parameters:
@@ -3087,17 +3087,17 @@ class DimensionDataMockHttp(StorageMockHttp, MockHttp):
         )
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
-    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_ipAddressList(
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_ipAddressList(
             self, method, url, body, headers):
         body = self.fixtures.load('ip_address_lists.xml')
         return httplib.OK, body, {}, httplib.responses[httplib.OK]
 
-    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_ipAddressList_FILTERBYNAME(
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_ipAddressList_FILTERBYNAME(
             self, method, url, body, headers):
         body = self.fixtures.load('ip_address_lists_FILTERBYNAME.xml')
         return httplib.OK, body, {}, httplib.responses[httplib.OK]
 
-    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_createIpAddressList(
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_createIpAddressList(
             self, method, url, body, headers):
         request = ET.fromstring(body)
         if request.tag != "{urn:didata.com:api:cloud:types}" \
@@ -3134,7 +3134,7 @@ class DimensionDataMockHttp(StorageMockHttp, MockHttp):
         )
         return httplib.OK, body, {}, httplib.responses[httplib.OK]
 
-    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_editIpAddressList(
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_editIpAddressList(
             self, method, url, body, headers):
         request = ET.fromstring(body)
         if request.tag != "{urn:didata.com:api:cloud:types}" \
@@ -3171,7 +3171,7 @@ class DimensionDataMockHttp(StorageMockHttp, MockHttp):
         )
         return httplib.OK, body, {}, httplib.responses[httplib.OK]
 
-    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_deleteIpAddressList(
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_deleteIpAddressList(
             self, method, url, body, headers):
         request = ET.fromstring(body)
         if request.tag != "{urn:didata.com:api:cloud:types}" \
@@ -3188,7 +3188,7 @@ class DimensionDataMockHttp(StorageMockHttp, MockHttp):
 
         return httplib.OK, body, {}, httplib.responses[httplib.OK]
 
-    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_portList(
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_portList(
             self, method, url, body, headers):
         body = self.fixtures.load(
             'port_list_lists.xml'
@@ -3196,7 +3196,7 @@ class DimensionDataMockHttp(StorageMockHttp, MockHttp):
 
         return httplib.OK, body, {}, httplib.responses[httplib.OK]
 
-    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_portList_c8c92ea3_2da8_4d51_8153_f39bec794d69(
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_portList_c8c92ea3_2da8_4d51_8153_f39bec794d69(
             self, method, url, body, headers):
         body = self.fixtures.load(
             'port_list_get.xml'
@@ -3204,7 +3204,7 @@ class DimensionDataMockHttp(StorageMockHttp, MockHttp):
 
         return httplib.OK, body, {}, httplib.responses[httplib.OK]
 
-    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_createPortList(
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_createPortList(
             self, method, url, body, headers):
 
         request = ET.fromstring(body)
@@ -3234,7 +3234,7 @@ class DimensionDataMockHttp(StorageMockHttp, MockHttp):
 
         return httplib.OK, body, {}, httplib.responses[httplib.OK]
 
-    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_editPortList(
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_editPortList(
             self, method, url, body, headers):
 
         request = ET.fromstring(body)
@@ -3260,7 +3260,7 @@ class DimensionDataMockHttp(StorageMockHttp, MockHttp):
 
         return httplib.OK, body, {}, httplib.responses[httplib.OK]
 
-    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_deletePortList(
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_deletePortList(
             self, method, url, body, headers):
         request = ET.fromstring(body)
         if request.tag != "{urn:didata.com:api:cloud:types}" \

http://git-wip-us.apache.org/repos/asf/libcloud/blob/03a2aa4e/libcloud/test/loadbalancer/test_dimensiondata.py
----------------------------------------------------------------------
diff --git a/libcloud/test/loadbalancer/test_dimensiondata.py b/libcloud/test/loadbalancer/test_dimensiondata.py
index 76afc25..2792d83 100644
--- a/libcloud/test/loadbalancer/test_dimensiondata.py
+++ b/libcloud/test/loadbalancer/test_dimensiondata.py
@@ -505,112 +505,112 @@ class DimensionDataMockHttp(MockHttp):
         body = self.fixtures.load('oec_0_9_myaccount.xml')
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
-    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_virtualListener(self, method, url, body, headers):
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_virtualListener(self, method, url, body, headers):
         body = self.fixtures.load(
             'networkDomainVip_virtualListener.xml')
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
-    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_virtualListener_6115469d_a8bb_445b_bb23_d23b5283f2b9(self, method, url, body, headers):
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_virtualListener_6115469d_a8bb_445b_bb23_d23b5283f2b9(self, method, url, body, headers):
         body = self.fixtures.load(
             'networkDomainVip_virtualListener_6115469d_a8bb_445b_bb23_d23b5283f2b9.xml')
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
-    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_pool(self, method, url, body, headers):
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_pool(self, method, url, body, headers):
         body = self.fixtures.load(
             'networkDomainVip_pool.xml')
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
-    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_pool_4d360b1f_bc2c_4ab7_9884_1f03ba2768f7(self, method, url, body, headers):
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_pool_4d360b1f_bc2c_4ab7_9884_1f03ba2768f7(self, method, url, body, headers):
         body = self.fixtures.load(
             'networkDomainVip_pool_4d360b1f_bc2c_4ab7_9884_1f03ba2768f7.xml')
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
-    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_poolMember(self, method, url, body, headers):
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_poolMember(self, method, url, body, headers):
         body = self.fixtures.load(
             'networkDomainVip_poolMember.xml')
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
-    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_poolMember_3dd806a2_c2c8_4c0c_9a4f_5219ea9266c0(self, method, url, body, headers):
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_poolMember_3dd806a2_c2c8_4c0c_9a4f_5219ea9266c0(self, method, url, body, headers):
         body = self.fixtures.load(
             'networkDomainVip_poolMember_3dd806a2_c2c8_4c0c_9a4f_5219ea9266c0.xml')
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
-    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_createPool(self, method, url, body, headers):
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_createPool(self, method, url, body, headers):
         body = self.fixtures.load(
             'networkDomainVip_createPool.xml')
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
-    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_createNode(self, method, url, body, headers):
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_createNode(self, method, url, body, headers):
         body = self.fixtures.load(
             'networkDomainVip_createNode.xml')
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
-    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_addPoolMember(self, method, url, body, headers):
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_addPoolMember(self, method, url, body, headers):
         body = self.fixtures.load(
             'networkDomainVip_addPoolMember.xml')
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
-    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_createVirtualListener(self, method, url, body, headers):
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_createVirtualListener(self, method, url, body, headers):
         body = self.fixtures.load(
             'networkDomainVip_createVirtualListener.xml')
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
-    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_removePoolMember(self, method, url, body, headers):
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_removePoolMember(self, method, url, body, headers):
         body = self.fixtures.load(
             'networkDomainVip_removePoolMember.xml')
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
-    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_deleteVirtualListener(self, method, url, body, headers):
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_deleteVirtualListener(self, method, url, body, headers):
         body = self.fixtures.load(
             'networkDomainVip_deleteVirtualListener.xml')
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
-    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_deletePool(self, method, url, body, headers):
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_deletePool(self, method, url, body, headers):
         body = self.fixtures.load(
             'networkDomainVip_deletePool.xml')
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
-    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_deleteNode(self, method, url, body, headers):
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_deleteNode(self, method, url, body, headers):
         body = self.fixtures.load(
             'networkDomainVip_deleteNode.xml')
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
-    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_node(self, method, url, body, headers):
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_node(self, method, url, body, headers):
         body = self.fixtures.load(
             'networkDomainVip_node.xml')
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
-    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_node_34de6ed6_46a4_4dae_a753_2f8d3840c6f9(self, method, url, body, headers):
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_node_34de6ed6_46a4_4dae_a753_2f8d3840c6f9(self, method, url, body, headers):
         body = self.fixtures.load(
             'networkDomainVip_node_34de6ed6_46a4_4dae_a753_2f8d3840c6f9.xml')
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
-    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_editNode(self, method, url, body, headers):
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_editNode(self, method, url, body, headers):
         body = self.fixtures.load(
             'networkDomainVip_editNode.xml')
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
-    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_editPool(self, method, url, body, headers):
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_editPool(self, method, url, body, headers):
         body = self.fixtures.load(
             'networkDomainVip_editPool.xml')
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
-    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_editPoolMember(self, method, url, body, headers):
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_editPoolMember(self, method, url, body, headers):
         body = self.fixtures.load(
             'networkDomainVip_editPoolMember.xml')
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
-    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_defaultHealthMonitor(self, method, url, body, headers):
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_defaultHealthMonitor(self, method, url, body, headers):
         body = self.fixtures.load(
             'networkDomainVip_defaultHealthMonitor.xml')
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
-    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_defaultPersistenceProfile(self, method, url, body, headers):
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_defaultPersistenceProfile(self, method, url, body, headers):
         body = self.fixtures.load(
             'networkDomainVip_defaultPersistenceProfile.xml')
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
-    def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_defaultIrule(self, method, url, body, headers):
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_defaultIrule(self, method, url, body, headers):
         body = self.fixtures.load(
             'networkDomainVip_defaultIrule.xml')
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])


[27/40] libcloud git commit: Attempt workaround for pylint bug on travis CI

Posted by an...@apache.org.
Attempt workaround for pylint bug on travis CI


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

Branch: refs/heads/trunk
Commit: 75da6d8fd9fddf60051c1983c6ef4e3394f55faf
Parents: ab681f6
Author: Samuel Chong <sa...@gmail.com>
Authored: Tue Nov 22 09:14:56 2016 +1100
Committer: Samuel Chong <sa...@gmail.com>
Committed: Tue Nov 22 09:14:56 2016 +1100

----------------------------------------------------------------------
 libcloud/common/dimensiondata.py | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/libcloud/blob/75da6d8f/libcloud/common/dimensiondata.py
----------------------------------------------------------------------
diff --git a/libcloud/common/dimensiondata.py b/libcloud/common/dimensiondata.py
index fdc3230..22f1da8 100644
--- a/libcloud/common/dimensiondata.py
+++ b/libcloud/common/dimensiondata.py
@@ -17,7 +17,8 @@ Dimension Data Common Components
 """
 from base64 import b64encode
 from time import sleep
-from distutils.version import LooseVersion
+
+from distutils.version import LooseVersion  # pylint: disable=import-error
 from libcloud.utils.py3 import httplib
 from libcloud.utils.py3 import b
 from libcloud.common.base import ConnectionUserAndKey, XmlResponse, RawResponse


[20/40] libcloud git commit: Resource file for api version 2.3

Posted by an...@apache.org.
Resource file for api version 2.3


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

Branch: refs/heads/trunk
Commit: 3ab1a465bddf2d9c1c88a3df28097ca589f717dd
Parents: bb1b810
Author: Samuel Chong <sa...@gmail.com>
Authored: Wed Nov 16 08:16:55 2016 +1100
Committer: Samuel Chong <sa...@gmail.com>
Committed: Wed Nov 16 08:16:55 2016 +1100

----------------------------------------------------------------------
 .../dimensiondata/image_customerImage.xml       | 50 ++++++++++++++++++++
 ...age_2ffa36c8_1848_49eb_b4fa_9d908775f68c.xml | 17 +++++++
 ...age_5234e5c7_01de_4411_8b6e_baeb8d91cf5d.xml | 17 +++++++
 .../fixtures/dimensiondata/image_osImage.xml    | 34 +++++++++++++
 ...age_6b4fb0c7_a57b_4f58_b59c_9958f94f971a.xml | 11 +++++
 ...age_c14b1a46_2428_44c1_9c1a_b20e6418d08c.xml | 12 +++++
 6 files changed, 141 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/libcloud/blob/3ab1a465/libcloud/test/compute/fixtures/dimensiondata/image_customerImage.xml
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/dimensiondata/image_customerImage.xml b/libcloud/test/compute/fixtures/dimensiondata/image_customerImage.xml
new file mode 100644
index 0000000..4e59e18
--- /dev/null
+++ b/libcloud/test/compute/fixtures/dimensiondata/image_customerImage.xml
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<customerImages xmlns="urn:didata.com:api:cloud:types" pageNumber="1" pageCount="35" totalCount="35" pageSize="250">
+    <customerImage id="5234e5c7-01de-4411-8b6e-baeb8d91cf5d" datacenterId="NA9">
+        <name>ImportedCustomerImage</name>
+        <description />
+        <operatingSystem id="REDHAT664" displayName="REDHAT6/64" family="UNIX" />
+        <cpu count="4" speed="STANDARD" coresPerSocket="1" />
+        <memoryGb>2</memoryGb>
+        <disk id="1a82316f-23ed-4fe9-b6d8-6b92ac467423" scsiId="0" sizeGb="12" speed="STANDARD" />
+        <createTime>2015-11-19T14:29:02.000Z</createTime>
+        <source type="IMPORT">
+        <artifact type="MF" value="ImportedCustomerImage.mf" date="2015-1119T14:28:54.000Z" />
+        <artifact type="OVF" value="ImportedCustomerImage.ovf" date="2015-1119T14:28:05.000Z" />
+        <artifact type="VMDK" value="ImportedCustomerImage-disk1.vmdk" date="2015-11-19T12:22:31.000Z" /></source>
+        <state>NORMAL</state>
+        <vmwareTools versionStatus="NEED_UPGRADE" runningStatus="NOT_RUNNING" apiVersion="8389" />
+        <virtualHardware version="vmx-10" upToDate="true" />
+    </customerImage>
+    <customerImage id="2ffa36c8-1848-49eb-b4fa-9d908775f68c" datacenterId="NA9">
+        <name>CustomerImageWithPricedSoftwareLabels</name>
+        <description />
+        <operatingSystem id="WIN2008S32" displayName="WIN2008S/32" family="WINDOWS" />
+        <cpu count="1" speed="STANDARD" coresPerSocket="1" />
+        <memoryGb>1</memoryGb>
+        <disk id="29455efc-51af-4b4d-91b3-d81ca0dff7d8" scsiId="0" sizeGb="50" speed="STANDARD" />
+        <softwareLabel>MSSQL2008R2S</softwareLabel>
+        <createTime>2015-11-03T15:25:34.000Z</createTime>
+        <source type="CLONE">
+            <artifact type="SERVER_ID" value="7c9c2551-269d-4274-a247126ba7c6215c" />
+        </source>
+        <state>NORMAL</state>
+        <vmwareTools versionStatus="CURRENT" runningStatus="NOT_RUNNING" />
+        <virtualHardware version="vmx-08" upToDate="false" />
+    </customerImage>
+    <customerImage id="1fc1844f-45d6-4364-b447-f7c7645b47de" datacenterId="NA9">
+        <name>CopiedCustomerImage</name>
+        <description />
+        <operatingSystem id="REDHAT664" displayName="REDHAT6/64" family="UNIX" />
+        <cpu count="1" speed="STANDARD" coresPerSocket="1" />
+        <memoryGb>2</memoryGb>
+        <disk id="42b20819-c161-4dec-aa94-73ec370a6e37" scsiId="0" sizeGb="10" speed="STANDARD" />
+        <createTime>2015-11-11T17:17:00.000Z</createTime>
+        <source type="COPY">
+            <artifact type="IMAGE_ID" value="0b8357b6-f156-4b27-b4fd-b81d09c15efc" />
+        </source>
+        <state>NORMAL</state>
+        <vmwareTools versionStatus="NEED_UPGRADE" runningStatus="NOT_RUNNING" apiVersion="9355" />
+        <virtualHardware version="vmx-10" upToDate="true" />
+    </customerImage>
+</customerImages>

http://git-wip-us.apache.org/repos/asf/libcloud/blob/3ab1a465/libcloud/test/compute/fixtures/dimensiondata/image_customerImage_2ffa36c8_1848_49eb_b4fa_9d908775f68c.xml
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/dimensiondata/image_customerImage_2ffa36c8_1848_49eb_b4fa_9d908775f68c.xml b/libcloud/test/compute/fixtures/dimensiondata/image_customerImage_2ffa36c8_1848_49eb_b4fa_9d908775f68c.xml
new file mode 100644
index 0000000..bff6183
--- /dev/null
+++ b/libcloud/test/compute/fixtures/dimensiondata/image_customerImage_2ffa36c8_1848_49eb_b4fa_9d908775f68c.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+    <customerImage xmlns="urn:didata.com:api:cloud:types" id="2ffa36c8-1848-49eb-b4fa-9d908775f68c" datacenterId="NA9">
+        <name>CustomerImageWithPricedSoftwareLabels</name>
+        <description />
+        <operatingSystem id="WIN2008S32" displayName="WIN2008S/32" family="WINDOWS" />
+        <cpu count="1" speed="STANDARD" coresPerSocket="1" />
+        <memoryGb>1</memoryGb>
+        <disk id="29455efc-51af-4b4d-91b3-d81ca0dff7d8" scsiId="0" sizeGb="50" speed="STANDARD" />
+        <softwareLabel>MSSQL2008R2S</softwareLabel>
+        <createTime>2015-11-03T15:25:34.000Z</createTime>
+        <source type="CLONE">
+            <artifact type="SERVER_ID" value="7c9c2551-269d-4274-a247126ba7c6215c" />
+        </source>
+        <state>NORMAL</state>
+        <vmwareTools versionStatus="CURRENT" runningStatus="NOT_RUNNING" />
+        <virtualHardware version="vmx-08" upToDate="false" />
+    </customerImage>

http://git-wip-us.apache.org/repos/asf/libcloud/blob/3ab1a465/libcloud/test/compute/fixtures/dimensiondata/image_customerImage_5234e5c7_01de_4411_8b6e_baeb8d91cf5d.xml
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/dimensiondata/image_customerImage_5234e5c7_01de_4411_8b6e_baeb8d91cf5d.xml b/libcloud/test/compute/fixtures/dimensiondata/image_customerImage_5234e5c7_01de_4411_8b6e_baeb8d91cf5d.xml
new file mode 100644
index 0000000..db5302d
--- /dev/null
+++ b/libcloud/test/compute/fixtures/dimensiondata/image_customerImage_5234e5c7_01de_4411_8b6e_baeb8d91cf5d.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+    <customerImage xmlns="urn:didata.com:api:cloud:types" id="5234e5c7-01de-4411-8b6e-baeb8d91cf5d" datacenterId="NA9">
+        <name>ImportedCustomerImage</name>
+        <description />
+        <operatingSystem id="REDHAT664" displayName="REDHAT6/64" family="UNIX" />
+        <cpu count="4" speed="STANDARD" coresPerSocket="1" />
+        <memoryGb>2</memoryGb>
+        <disk id="1a82316f-23ed-4fe9-b6d8-6b92ac467423" scsiId="0" sizeGb="12" speed="STANDARD" />
+        <createTime>2015-11-19T14:29:02.000Z</createTime>
+        <source type="IMPORT">
+        <artifact type="MF" value="ImportedCustomerImage.mf" date="2015-1119T14:28:54.000Z" />
+        <artifact type="OVF" value="ImportedCustomerImage.ovf" date="2015-1119T14:28:05.000Z" />
+        <artifact type="VMDK" value="ImportedCustomerImage-disk1.vmdk" date="2015-11-19T12:22:31.000Z" /></source>
+        <state>NORMAL</state>
+        <vmwareTools versionStatus="NEED_UPGRADE" runningStatus="NOT_RUNNING" apiVersion="8389" />
+        <virtualHardware version="vmx-10" upToDate="true" />
+    </customerImage>

http://git-wip-us.apache.org/repos/asf/libcloud/blob/3ab1a465/libcloud/test/compute/fixtures/dimensiondata/image_osImage.xml
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/dimensiondata/image_osImage.xml b/libcloud/test/compute/fixtures/dimensiondata/image_osImage.xml
new file mode 100644
index 0000000..1f884a9
--- /dev/null
+++ b/libcloud/test/compute/fixtures/dimensiondata/image_osImage.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<osImages xmlns="urn:didata.com:api:cloud:types" pageNumber="1" pageCount="47" totalCount="47" pageSize="250">
+    <osImage id="c14b1a46-2428-44c1-9c1a-b20e6418d08c" datacenterId="NA9">
+        <name>RedHat 6 64-bit 2 CPU</name>
+        <description>RedHat 6.6 Enterprise (Santiago) 64-bit</description>
+        <operatingSystem id="REDHAT664" displayName="REDHAT6/64" family="UNIX" />
+        <cpu count="2" speed="STANDARD" coresPerSocket="1" />
+        <memoryGb>4</memoryGb>
+        <disk id="a02b7244-99d8-4889-84a5-5e4373c1bb26" scsiId="0" sizeGb="10" speed="STANDARD" />
+        <createTime>2015-09-17T11:23:48.000Z</createTime>
+        <osImageKey>T-RHEL-6-64-2-4-10</osImageKey>
+    </osImage>
+    <osImage id="6b4fb0c7-a57b-4f58-b59c-9958f94f971a" datacenterId="NA9">
+        <name>Win2012 DC 2 CPU</name>
+        <description>Windows 2012 Datacenter</description>
+        <operatingSystem id="WIN2012DC64" displayName="WIN2012DC/64" family="WINDOWS" />
+        <cpu count="2" speed="STANDARD" coresPerSocket="1" />
+        <memoryGb>4</memoryGb>
+        <disk id="f5e01854-a211-4ec6-96d6-2753b6d47877" scsiId="0" sizeGb="50" speed="STANDARD" />
+        <createTime>2015-09-17T11:44:43.000Z</createTime>
+        <osImageKey>T-WIN-2012-DATACTR-64-2-4-50</osImageKey>
+    </osImage>
+    <osImage id="3ebf3c0f-90fe-4a8b-8585-6e65b316592c" datacenterId="NA9">
+        <name>Win2008 Std 32-bit 2 CPU</name>
+        <description>Windows 2008 Enterprise R2 32-bit installed with Microsoft SQL Server 2012 Standard Edition</description>
+        <operatingSystem id="WIN2008S32" displayName="WIN2008S/32" family="WINDOWS" />
+        <cpu count="2" speed="STANDARD" coresPerSocket="1" />
+        <memoryGb>4</memoryGb>
+        <disk id="6e5b5112-0eae-44eb-83cd-1bd0d58fbeab" scsiId="0" sizeGb="50" speed="STANDARD" />
+        <softwareLabel>MSSQL2008R2S</softwareLabel>
+        <createTime>2014-11-20T12:54:22.000Z</createTime>
+        <osImageKey>T-WIN-2008-ENT-32-2-4-50</osImageKey>
+    </osImage>
+</osImages>

http://git-wip-us.apache.org/repos/asf/libcloud/blob/3ab1a465/libcloud/test/compute/fixtures/dimensiondata/image_osImage_6b4fb0c7_a57b_4f58_b59c_9958f94f971a.xml
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/dimensiondata/image_osImage_6b4fb0c7_a57b_4f58_b59c_9958f94f971a.xml b/libcloud/test/compute/fixtures/dimensiondata/image_osImage_6b4fb0c7_a57b_4f58_b59c_9958f94f971a.xml
new file mode 100644
index 0000000..1631137
--- /dev/null
+++ b/libcloud/test/compute/fixtures/dimensiondata/image_osImage_6b4fb0c7_a57b_4f58_b59c_9958f94f971a.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+  <osImage xmlns="urn:didata.com:api:cloud:types" id="6b4fb0c7-a57b-4f58-b59c-9958f94f971a" datacenterId="NA9">
+    <name>Win2012 DC 2 CPU</name>
+    <description>Windows 2012 Datacenter</description>
+    <operatingSystem id="WIN2012DC64" displayName="WIN2012DC/64" family="WINDOWS" />
+    <cpu count="2" speed="STANDARD" coresPerSocket="1" />
+    <memoryGb>4</memoryGb>
+    <disk id="f5e01854-a211-4ec6-96d6-2753b6d47877" scsiId="0" sizeGb="50" speed="STANDARD" />
+    <createTime>2015-09-17T11:44:43.000Z</createTime>
+    <osImageKey>T-WIN-2012-DATACTR-64-2-4-50</osImageKey>
+  </osImage>

http://git-wip-us.apache.org/repos/asf/libcloud/blob/3ab1a465/libcloud/test/compute/fixtures/dimensiondata/image_osImage_c14b1a46_2428_44c1_9c1a_b20e6418d08c.xml
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/dimensiondata/image_osImage_c14b1a46_2428_44c1_9c1a_b20e6418d08c.xml b/libcloud/test/compute/fixtures/dimensiondata/image_osImage_c14b1a46_2428_44c1_9c1a_b20e6418d08c.xml
new file mode 100644
index 0000000..27d6c25
--- /dev/null
+++ b/libcloud/test/compute/fixtures/dimensiondata/image_osImage_c14b1a46_2428_44c1_9c1a_b20e6418d08c.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+  <osImage xmlns="urn:didata.com:api:cloud:types" id="c14b1a46-2428-44c1-9c1a-b20e6418d08c" datacenterId="NA9">
+    <name>RedHat 6 64-bit 2 CPU</name>
+    <description>RedHat 6.6 Enterprise (Santiago) 64-bit</description>
+    <operatingSystem id="REDHAT664" displayName="REDHAT6/64" family="UNIX" />
+    <cpu count="2" speed="STANDARD" coresPerSocket="1" />
+    <memoryGb>4</memoryGb>
+    <disk id="a02b7244-99d8-4889-84a5-5e4373c1bb26" scsiId="0" sizeGb="10" speed="STANDARD" />
+    <createTime>2015-09-17T11:23:48.000Z</createTime>
+    <osImageKey>T-RHEL-6-64-2-4-10</osImageKey>
+  </osImage>
+


[16/40] libcloud git commit: Unit tests for 2.3

Posted by an...@apache.org.
http://git-wip-us.apache.org/repos/asf/libcloud/blob/bb1b8104/libcloud/test/compute/test_dimensiondata_v2_3.py
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/test_dimensiondata_v2_3.py b/libcloud/test/compute/test_dimensiondata_v2_3.py
new file mode 100644
index 0000000..20c544c
--- /dev/null
+++ b/libcloud/test/compute/test_dimensiondata_v2_3.py
@@ -0,0 +1,3282 @@
+# 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.
+
+try:
+    from lxml import etree as ET
+except ImportError:
+    from xml.etree import ElementTree as ET
+
+import sys
+from types import GeneratorType
+from libcloud.utils.py3 import httplib
+
+from libcloud.common.types import InvalidCredsError
+from libcloud.common.dimensiondata import DimensionDataAPIException, NetworkDomainServicePlan
+from libcloud.common.dimensiondata import DimensionDataServerCpuSpecification, DimensionDataServerDisk, DimensionDataServerVMWareTools
+from libcloud.common.dimensiondata import DimensionDataTag, DimensionDataTagKey
+from libcloud.common.dimensiondata import DimensionDataIpAddress, \
+    DimensionDataIpAddressList, DimensionDataChildIpAddressList, \
+    DimensionDataPortList, DimensionDataPort, DimensionDataChildPortList
+from libcloud.common.dimensiondata import TYPES_URN
+from libcloud.compute.drivers.dimensiondata import DimensionDataNodeDriver as DimensionData
+from libcloud.compute.drivers.dimensiondata import DimensionDataNic
+from libcloud.compute.base import Node, NodeAuthPassword, NodeLocation
+from libcloud.test import MockHttp, unittest, MockRawResponse, StorageMockHttp
+from libcloud.test.compute import TestCaseMixin
+from libcloud.test.file_fixtures import ComputeFileFixtures
+from libcloud.test.secrets import DIMENSIONDATA_PARAMS
+from libcloud.utils.xml import fixxpath, findtext, findall
+
+
+class DimensionDataTests(unittest.TestCase, TestCaseMixin):
+
+    def setUp(self):
+        DimensionData.connectionCls.active_api_version = '2.3'
+        DimensionData.connectionCls.conn_classes = (None, DimensionDataMockHttp)
+        DimensionData.connectionCls.rawResponseCls = \
+            DimensionDataMockRawResponse
+        DimensionDataMockHttp.type = None
+        self.driver = DimensionData(*DIMENSIONDATA_PARAMS)
+
+    def test_invalid_region(self):
+        with self.assertRaises(ValueError):
+            DimensionData(*DIMENSIONDATA_PARAMS, region='blah')
+
+    def test_invalid_creds(self):
+        DimensionDataMockHttp.type = 'UNAUTHORIZED'
+        with self.assertRaises(InvalidCredsError):
+            self.driver.list_nodes()
+
+    def test_get_account_details(self):
+        DimensionDataMockHttp.type = None
+        ret = self.driver.connection.get_account_details()
+        self.assertEqual(ret.full_name, 'Test User')
+        self.assertEqual(ret.first_name, 'Test')
+        self.assertEqual(ret.email, 'test@example.com')
+
+    def test_list_locations_response(self):
+        DimensionDataMockHttp.type = None
+        ret = self.driver.list_locations()
+        self.assertEqual(len(ret), 5)
+        first_loc = ret[0]
+        self.assertEqual(first_loc.id, 'NA3')
+        self.assertEqual(first_loc.name, 'US - West')
+        self.assertEqual(first_loc.country, 'US')
+
+    def test_list_nodes_response(self):
+        DimensionDataMockHttp.type = None
+        ret = self.driver.list_nodes()
+        self.assertEqual(len(ret), 7)
+
+    def test_node_extras(self):
+        DimensionDataMockHttp.type = None
+        ret = self.driver.list_nodes()
+        self.assertTrue(isinstance(ret[0].extra['vmWareTools'], DimensionDataServerVMWareTools))
+        self.assertTrue(isinstance(ret[0].extra['cpu'], DimensionDataServerCpuSpecification))
+        self.assertTrue(isinstance(ret[0].extra['disks'], list))
+        self.assertTrue(isinstance(ret[0].extra['disks'][0], DimensionDataServerDisk))
+        self.assertEqual(ret[0].extra['disks'][0].size_gb, 10)
+        self.assertTrue(isinstance(ret[1].extra['disks'], list))
+        self.assertTrue(isinstance(ret[1].extra['disks'][0], DimensionDataServerDisk))
+        self.assertEqual(ret[1].extra['disks'][0].size_gb, 10)
+
+    def test_server_states(self):
+        DimensionDataMockHttp.type = None
+        ret = self.driver.list_nodes()
+        self.assertTrue(ret[0].state == 'running')
+        self.assertTrue(ret[1].state == 'starting')
+        self.assertTrue(ret[2].state == 'stopping')
+        self.assertTrue(ret[3].state == 'reconfiguring')
+        self.assertTrue(ret[4].state == 'running')
+        self.assertTrue(ret[5].state == 'terminated')
+        self.assertTrue(ret[6].state == 'stopped')
+        self.assertEqual(len(ret), 7)
+
+    def test_list_nodes_response_PAGINATED(self):
+        DimensionDataMockHttp.type = 'PAGINATED'
+        ret = self.driver.list_nodes()
+        self.assertEqual(len(ret), 9)
+
+    def test_paginated_mcp2_call_EMPTY(self):
+        # cache org
+        self.driver.connection._get_orgId()
+        DimensionDataMockHttp.type = 'EMPTY'
+        node_list_generator = self.driver.connection.paginated_request_with_orgId_api_2('server/server')
+        empty_node_list = []
+        for node_list in node_list_generator:
+            empty_node_list.extend(node_list)
+        self.assertTrue(len(empty_node_list) == 0)
+
+    def test_paginated_mcp2_call_PAGED_THEN_EMPTY(self):
+        # cache org
+        self.driver.connection._get_orgId()
+        DimensionDataMockHttp.type = 'PAGED_THEN_EMPTY'
+        node_list_generator = self.driver.connection.paginated_request_with_orgId_api_2('server/server')
+        final_node_list = []
+        for node_list in node_list_generator:
+            final_node_list.extend(node_list)
+        self.assertTrue(len(final_node_list) == 2)
+
+    def test_paginated_mcp2_call_with_page_size(self):
+        # cache org
+        self.driver.connection._get_orgId()
+        DimensionDataMockHttp.type = 'PAGESIZE50'
+        node_list_generator = self.driver.connection.paginated_request_with_orgId_api_2('server/server', page_size=50)
+        self.assertTrue(isinstance(node_list_generator, GeneratorType))
+
+    # We're making sure here the filters make it to the URL
+    # See  _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_server_ALLFILTERS for asserts
+    def test_list_nodes_response_strings_ALLFILTERS(self):
+        DimensionDataMockHttp.type = 'ALLFILTERS'
+        ret = self.driver.list_nodes(ex_location='fake_loc', ex_name='fake_name',
+                                     ex_ipv6='fake_ipv6', ex_ipv4='fake_ipv4', ex_vlan='fake_vlan',
+                                     ex_image='fake_image', ex_deployed=True,
+                                     ex_started=True, ex_state='fake_state',
+                                     ex_network='fake_network', ex_network_domain='fake_network_domain')
+        self.assertTrue(isinstance(ret, list))
+        self.assertEqual(len(ret), 7)
+
+        node = ret[3]
+        self.assertTrue(isinstance(node.extra['disks'], list))
+        self.assertTrue(isinstance(node.extra['disks'][0], DimensionDataServerDisk))
+        self.assertEqual(node.size.id, '1')
+        self.assertEqual(node.image.id, '3ebf3c0f-90fe-4a8b-8585-6e65b316592c')
+        self.assertEqual(node.image.name, 'WIN2008S/32')
+        disk = node.extra['disks'][0]
+        self.assertEqual(disk.id, "c2e1f199-116e-4dbc-9960-68720b832b0a")
+        self.assertEqual(disk.scsi_id, 0)
+        self.assertEqual(disk.size_gb, 50)
+        self.assertEqual(disk.speed, "STANDARD")
+        self.assertEqual(disk.state, "NORMAL")
+
+    def test_list_nodes_response_LOCATION(self):
+        DimensionDataMockHttp.type = None
+        ret = self.driver.list_locations()
+        first_loc = ret[0]
+        ret = self.driver.list_nodes(ex_location=first_loc)
+        for node in ret:
+            self.assertEqual(node.extra['datacenterId'], 'NA3')
+
+    def test_list_nodes_response_LOCATION_STR(self):
+        DimensionDataMockHttp.type = None
+        ret = self.driver.list_nodes(ex_location='NA3')
+        for node in ret:
+            self.assertEqual(node.extra['datacenterId'], 'NA3')
+
+    def test_list_sizes_response(self):
+        DimensionDataMockHttp.type = None
+        ret = self.driver.list_sizes()
+        self.assertEqual(len(ret), 1)
+        size = ret[0]
+        self.assertEqual(size.name, 'default')
+
+    def test_reboot_node_response(self):
+        node = Node(id='11', name=None, state=None,
+                    public_ips=None, private_ips=None, driver=self.driver)
+        ret = node.reboot()
+        self.assertTrue(ret is True)
+
+    def test_reboot_node_response_INPROGRESS(self):
+        DimensionDataMockHttp.type = 'INPROGRESS'
+        node = Node(id='11', name=None, state=None,
+                    public_ips=None, private_ips=None, driver=self.driver)
+        with self.assertRaises(DimensionDataAPIException):
+            node.reboot()
+
+    def test_destroy_node_response(self):
+        node = Node(id='11', name=None, state=None,
+                    public_ips=None, private_ips=None, driver=self.driver)
+        ret = node.destroy()
+        self.assertTrue(ret is True)
+
+    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)
+        with self.assertRaises(DimensionDataAPIException):
+            node.destroy()
+
+    def test_list_images(self):
+        images = self.driver.list_images()
+        self.assertEqual(len(images), 3)
+        self.assertEqual(images[0].name, 'RedHat 6 64-bit 2 CPU')
+        self.assertEqual(images[0].id, 'c14b1a46-2428-44c1-9c1a-b20e6418d08c')
+        self.assertEqual(images[0].extra['location'].id, 'NA9')
+        self.assertEqual(images[0].extra['cpu'].cpu_count, 2)
+        self.assertEqual(images[0].extra['OS_displayName'], 'REDHAT6/64')
+
+    def test_clean_failed_deployment_response_with_node(self):
+        node = Node(id='11', name=None, state=None,
+                    public_ips=None, private_ips=None, driver=self.driver)
+        ret = self.driver.ex_clean_failed_deployment(node)
+        self.assertTrue(ret is True)
+
+    def test_clean_failed_deployment_response_with_node_id(self):
+        node = 'e75ead52-692f-4314-8725-c8a4f4d13a87'
+        ret = self.driver.ex_clean_failed_deployment(node)
+        self.assertTrue(ret is True)
+
+    def test_ex_list_customer_images(self):
+        images = self.driver.ex_list_customer_images()
+        self.assertEqual(len(images), 3)
+        self.assertEqual(images[0].name, 'ImportedCustomerImage')
+        self.assertEqual(images[0].id, '5234e5c7-01de-4411-8b6e-baeb8d91cf5d')
+        self.assertEqual(images[0].extra['location'].id, 'NA9')
+        self.assertEqual(images[0].extra['cpu'].cpu_count, 4)
+        self.assertEqual(images[0].extra['OS_displayName'], 'REDHAT6/64')
+
+    def test_create_mcp1_node_optional_param(self):
+        root_pw = NodeAuthPassword('pass123')
+        image = self.driver.list_images()[0]
+        network = self.driver.ex_list_networks()[0]
+        cpu_spec = DimensionDataServerCpuSpecification(cpu_count='4',
+                                                       cores_per_socket='2',
+                                                       performance='STANDARD')
+        disks = [DimensionDataServerDisk(scsi_id='0', speed='HIGHPERFORMANCE')]
+        node = self.driver.create_node(name='test2', image=image, auth=root_pw,
+                                       ex_description='test2 node',
+                                       ex_network=network,
+                                       ex_is_started=False,
+                                       ex_memory_gb=8,
+                                       ex_disks=disks,
+                                       ex_cpu_specification=cpu_spec,
+                                       ex_primary_dns='10.0.0.5',
+                                       ex_secondary_dns='10.0.0.6'
+                                       )
+        self.assertEqual(node.id, 'e75ead52-692f-4314-8725-c8a4f4d13a87')
+        self.assertEqual(node.extra['status'].action, 'DEPLOY_SERVER')
+
+    def test_create_mcp1_node_response_no_pass_random_gen(self):
+        image = self.driver.list_images()[0]
+        network = self.driver.ex_list_networks()[0]
+        node = self.driver.create_node(name='test2', image=image, auth=None,
+                                       ex_description='test2 node',
+                                       ex_network=network,
+                                       ex_is_started=False)
+        self.assertEqual(node.id, 'e75ead52-692f-4314-8725-c8a4f4d13a87')
+        self.assertEqual(node.extra['status'].action, 'DEPLOY_SERVER')
+        self.assertTrue('password' in node.extra)
+
+    def test_create_mcp1_node_response_no_pass_customer_windows(self):
+        image = self.driver.ex_list_customer_images()[1]
+        network = self.driver.ex_list_networks()[0]
+        node = self.driver.create_node(name='test2', image=image, auth=None,
+                                       ex_description='test2 node', ex_network=network,
+                                       ex_is_started=False)
+        self.assertEqual(node.id, 'e75ead52-692f-4314-8725-c8a4f4d13a87')
+        self.assertEqual(node.extra['status'].action, 'DEPLOY_SERVER')
+        self.assertTrue('password' in node.extra)
+
+    def test_create_mcp1_node_response_no_pass_customer_windows_STR(self):
+        image = self.driver.ex_list_customer_images()[1].id
+        network = self.driver.ex_list_networks()[0]
+        node = self.driver.create_node(name='test2', image=image, auth=None,
+                                       ex_description='test2 node', ex_network=network,
+                                       ex_is_started=False)
+        self.assertEqual(node.id, 'e75ead52-692f-4314-8725-c8a4f4d13a87')
+        self.assertEqual(node.extra['status'].action, 'DEPLOY_SERVER')
+        self.assertTrue('password' in node.extra)
+
+    def test_create_mcp1_node_response_no_pass_customer_linux(self):
+        image = self.driver.ex_list_customer_images()[0]
+        network = self.driver.ex_list_networks()[0]
+        node = self.driver.create_node(name='test2', image=image, auth=None,
+                                       ex_description='test2 node', ex_network=network,
+                                       ex_is_started=False)
+        self.assertEqual(node.id, 'e75ead52-692f-4314-8725-c8a4f4d13a87')
+        self.assertEqual(node.extra['status'].action, 'DEPLOY_SERVER')
+        self.assertTrue('password' not in node.extra)
+
+    def test_create_mcp1_node_response_no_pass_customer_linux_STR(self):
+        image = self.driver.ex_list_customer_images()[0].id
+        network = self.driver.ex_list_networks()[0]
+        node = self.driver.create_node(name='test2', image=image, auth=None,
+                                       ex_description='test2 node', ex_network=network,
+                                       ex_is_started=False)
+        self.assertEqual(node.id, 'e75ead52-692f-4314-8725-c8a4f4d13a87')
+        self.assertEqual(node.extra['status'].action, 'DEPLOY_SERVER')
+        self.assertTrue('password' not in node.extra)
+
+    def test_create_mcp1_node_response_STR(self):
+        rootPw = 'pass123'
+        image = self.driver.list_images()[0].id
+        network = self.driver.ex_list_networks()[0].id
+        node = self.driver.create_node(name='test2', image=image, auth=rootPw,
+                                       ex_description='test2 node', ex_network=network,
+                                       ex_is_started=False)
+        self.assertEqual(node.id, 'e75ead52-692f-4314-8725-c8a4f4d13a87')
+        self.assertEqual(node.extra['status'].action, 'DEPLOY_SERVER')
+
+    def test_create_node_response_network_domain(self):
+        rootPw = NodeAuthPassword('pass123')
+        location = self.driver.ex_get_location_by_id('NA9')
+        image = self.driver.list_images(location=location)[0]
+        network_domain = self.driver.ex_list_network_domains(location=location)[0]
+        vlan = self.driver.ex_list_vlans(location=location)[0]
+        cpu = DimensionDataServerCpuSpecification(
+            cpu_count=4,
+            cores_per_socket=1,
+            performance='HIGHPERFORMANCE'
+        )
+        node = self.driver.create_node(name='test2', image=image, auth=rootPw,
+                                       ex_description='test2 node',
+                                       ex_network_domain=network_domain,
+                                       ex_vlan=vlan,
+                                       ex_is_started=False, ex_cpu_specification=cpu,
+                                       ex_memory_gb=4)
+        self.assertEqual(node.id, 'e75ead52-692f-4314-8725-c8a4f4d13a87')
+        self.assertEqual(node.extra['status'].action, 'DEPLOY_SERVER')
+
+    def test_create_node_response_network_domain_STR(self):
+        rootPw = NodeAuthPassword('pass123')
+        location = self.driver.ex_get_location_by_id('NA9')
+        image = self.driver.list_images(location=location)[0]
+        network_domain = self.driver.ex_list_network_domains(location=location)[0].id
+        vlan = self.driver.ex_list_vlans(location=location)[0].id
+        cpu = DimensionDataServerCpuSpecification(
+            cpu_count=4,
+            cores_per_socket=1,
+            performance='HIGHPERFORMANCE'
+        )
+        node = self.driver.create_node(name='test2', image=image, auth=rootPw,
+                                       ex_description='test2 node',
+                                       ex_network_domain=network_domain,
+                                       ex_vlan=vlan,
+                                       ex_is_started=False, ex_cpu_specification=cpu,
+                                       ex_memory_gb=4)
+        self.assertEqual(node.id, 'e75ead52-692f-4314-8725-c8a4f4d13a87')
+        self.assertEqual(node.extra['status'].action, 'DEPLOY_SERVER')
+
+    def test_create_mcp1_node_no_network(self):
+        rootPw = NodeAuthPassword('pass123')
+        image = self.driver.list_images()[0]
+        with self.assertRaises(InvalidRequestError):
+            self.driver.create_node(name='test2',
+                                    image=image,
+                                    auth=rootPw,
+                                    ex_description='test2 node',
+                                    ex_network=None,
+                                    ex_is_started=False)
+
+    def test_create_node_mcp1_ipv4(self):
+        rootPw = NodeAuthPassword('pass123')
+        image = self.driver.list_images()[0]
+        node = self.driver.create_node(name='test2',
+                                       image=image,
+                                       auth=rootPw,
+                                       ex_description='test2 node',
+                                       ex_network='fakenetwork',
+                                       ex_primary_ipv4='10.0.0.1',
+                                       ex_is_started=False)
+        self.assertEqual(node.id, 'e75ead52-692f-4314-8725-c8a4f4d13a87')
+        self.assertEqual(node.extra['status'].action, 'DEPLOY_SERVER')
+
+    def test_create_node_mcp1_network(self):
+        rootPw = NodeAuthPassword('pass123')
+        image = self.driver.list_images()[0]
+        node = self.driver.create_node(name='test2',
+                                       image=image,
+                                       auth=rootPw,
+                                       ex_description='test2 node',
+                                       ex_network='fakenetwork',
+                                       ex_is_started=False)
+        self.assertEqual(node.id, 'e75ead52-692f-4314-8725-c8a4f4d13a87')
+        self.assertEqual(node.extra['status'].action, 'DEPLOY_SERVER')
+
+    def test_create_node_mcp2_vlan(self):
+        rootPw = NodeAuthPassword('pass123')
+        image = self.driver.list_images()[0]
+        node = self.driver.create_node(name='test2',
+                                       image=image,
+                                       auth=rootPw,
+                                       ex_description='test2 node',
+                                       ex_network_domain='fakenetworkdomain',
+                                       ex_vlan='fakevlan',
+                                       ex_is_started=False)
+        self.assertEqual(node.id, 'e75ead52-692f-4314-8725-c8a4f4d13a87')
+        self.assertEqual(node.extra['status'].action, 'DEPLOY_SERVER')
+
+    def test_create_node_mcp2_ipv4(self):
+        rootPw = NodeAuthPassword('pass123')
+        image = self.driver.list_images()[0]
+        node = self.driver.create_node(name='test2',
+                                       image=image,
+                                       auth=rootPw,
+                                       ex_description='test2 node',
+                                       ex_network_domain='fakenetworkdomain',
+                                       ex_primary_ipv4='10.0.0.1',
+                                       ex_is_started=False)
+        self.assertEqual(node.id, 'e75ead52-692f-4314-8725-c8a4f4d13a87')
+        self.assertEqual(node.extra['status'].action, 'DEPLOY_SERVER')
+
+    def test_create_node_network_domain_no_vlan_or_ipv4(self):
+        rootPw = NodeAuthPassword('pass123')
+        image = self.driver.list_images()[0]
+        with self.assertRaises(ValueError):
+            self.driver.create_node(name='test2',
+                                    image=image,
+                                    auth=rootPw,
+                                    ex_description='test2 node',
+                                    ex_network_domain='fake_network_domain',
+                                    ex_is_started=False)
+
+    def test_create_node_response(self):
+        rootPw = NodeAuthPassword('pass123')
+        image = self.driver.list_images()[0]
+        node = self.driver.create_node(
+            name='test3',
+            image=image,
+            auth=rootPw,
+            ex_network_domain='fakenetworkdomain',
+            ex_primary_nic_vlan='fakevlan'
+        )
+        self.assertEqual(node.id, 'e75ead52-692f-4314-8725-c8a4f4d13a87')
+        self.assertEqual(node.extra['status'].action, 'DEPLOY_SERVER')
+
+    def test_create_node_ms_time_zone(self):
+        rootPw = NodeAuthPassword('pass123')
+        image = self.driver.list_images()[0]
+        node = self.driver.create_node(
+            name='test3',
+            image=image,
+            auth=rootPw,
+            ex_network_domain='fakenetworkdomain',
+            ex_primary_nic_vlan='fakevlan',
+            ex_microsoft_time_zone='040'
+        )
+        self.assertEqual(node.id, 'e75ead52-692f-4314-8725-c8a4f4d13a87')
+        self.assertEqual(node.extra['status'].action, 'DEPLOY_SERVER')
+
+    def test_create_node_ambigious_mcps_fail(self):
+        rootPw = NodeAuthPassword('pass123')
+        image = self.driver.list_images()[0]
+        with self.assertRaises(ValueError):
+            self.driver.create_node(
+                name='test3',
+                image=image,
+                auth=rootPw,
+                ex_network_domain='fakenetworkdomain',
+                ex_network='fakenetwork',
+                ex_primary_nic_vlan='fakevlan'
+            )
+
+    def test_create_node_no_network_domain_fail(self):
+        rootPw = NodeAuthPassword('pass123')
+        image = self.driver.list_images()[0]
+        with self.assertRaises(ValueError):
+            self.driver.create_node(
+                name='test3',
+                image=image,
+                auth=rootPw,
+                ex_primary_nic_vlan='fakevlan'
+            )
+
+    def test_create_node_no_primary_nic_fail(self):
+        rootPw = NodeAuthPassword('pass123')
+        image = self.driver.list_images()[0]
+        with self.assertRaises(ValueError):
+            self.driver.create_node(
+                name='test3',
+                image=image,
+                auth=rootPw,
+                ex_network_domain='fakenetworkdomain'
+            )
+
+    def test_create_node_primary_vlan_nic(self):
+        rootPw = NodeAuthPassword('pass123')
+        image = self.driver.list_images()[0]
+        node = self.driver.create_node(
+            name='test3',
+            image=image,
+            auth=rootPw,
+            ex_network_domain='fakenetworkdomain',
+            ex_primary_nic_vlan='fakevlan',
+            ex_primary_nic_network_adapter='v1000'
+        )
+        self.assertEqual(node.id, 'e75ead52-692f-4314-8725-c8a4f4d13a87')
+        self.assertEqual(node.extra['status'].action, 'DEPLOY_SERVER')
+
+    def test_create_node_primary_ipv4(self):
+        rootPw = 'pass123'
+        image = self.driver.list_images()[0]
+        node = self.driver.create_node(
+            name='test3',
+            image=image,
+            auth=rootPw,
+            ex_network_domain='fakenetworkdomain',
+            ex_primary_nic_private_ipv4='10.0.0.1'
+        )
+        self.assertEqual(node.id, 'e75ead52-692f-4314-8725-c8a4f4d13a87')
+        self.assertEqual(node.extra['status'].action, 'DEPLOY_SERVER')
+
+    def test_create_node_both_primary_nic_and_vlan_fail(self):
+        rootPw = NodeAuthPassword('pass123')
+        image = self.driver.list_images()[0]
+        with self.assertRaises(ValueError):
+            self.driver.create_node(
+                name='test3',
+                image=image,
+                auth=rootPw,
+                ex_network_domain='fakenetworkdomain',
+                ex_primary_nic_private_ipv4='10.0.0.1',
+                ex_primary_nic_vlan='fakevlan'
+            )
+
+    def test_create_node_cpu_specification(self):
+        rootPw = NodeAuthPassword('pass123')
+        image = self.driver.list_images()[0]
+        cpu_spec = DimensionDataServerCpuSpecification(cpu_count='4',
+                                                       cores_per_socket='2',
+                                                       performance='STANDARD')
+        node = self.driver.create_node(name='test2',
+                                       image=image,
+                                       auth=rootPw,
+                                       ex_description='test2 node',
+                                       ex_network_domain='fakenetworkdomain',
+                                       ex_primary_nic_private_ipv4='10.0.0.1',
+                                       ex_is_started=False,
+                                       ex_cpu_specification=cpu_spec)
+        self.assertEqual(node.id, 'e75ead52-692f-4314-8725-c8a4f4d13a87')
+        self.assertEqual(node.extra['status'].action, 'DEPLOY_SERVER')
+
+    def test_create_node_memory(self):
+        rootPw = NodeAuthPassword('pass123')
+        image = self.driver.list_images()[0]
+
+        node = self.driver.create_node(name='test2',
+                                       image=image,
+                                       auth=rootPw,
+                                       ex_description='test2 node',
+                                       ex_network_domain='fakenetworkdomain',
+                                       ex_primary_nic_private_ipv4='10.0.0.1',
+                                       ex_is_started=False,
+                                       ex_memory_gb=8)
+        self.assertEqual(node.id, 'e75ead52-692f-4314-8725-c8a4f4d13a87')
+        self.assertEqual(node.extra['status'].action, 'DEPLOY_SERVER')
+
+    def test_create_node_disks(self):
+        rootPw = NodeAuthPassword('pass123')
+        image = self.driver.list_images()[0]
+        disks = [DimensionDataServerDisk(scsi_id='0', speed='HIGHPERFORMANCE')]
+        node = self.driver.create_node(name='test2',
+                                       image=image,
+                                       auth=rootPw,
+                                       ex_description='test2 node',
+                                       ex_network_domain='fakenetworkdomain',
+                                       ex_primary_nic_private_ipv4='10.0.0.1',
+                                       ex_is_started=False,
+                                       ex_disks=disks)
+        self.assertEqual(node.id, 'e75ead52-692f-4314-8725-c8a4f4d13a87')
+        self.assertEqual(node.extra['status'].action, 'DEPLOY_SERVER')
+
+    def test_create_node_disks_fail(self):
+        root_pw = NodeAuthPassword('pass123')
+        image = self.driver.list_images()[0]
+        disks = 'blah'
+        with self.assertRaises(TypeError):
+            self.driver.create_node(name='test2',
+                                    image=image,
+                                    auth=root_pw,
+                                    ex_description='test2 node',
+                                    ex_network_domain='fakenetworkdomain',
+                                    ex_primary_nic_private_ipv4='10.0.0.1',
+                                    ex_is_started=False,
+                                    ex_disks=disks)
+
+    def test_create_node_ipv4_gateway(self):
+        rootPw = NodeAuthPassword('pass123')
+        image = self.driver.list_images()[0]
+        node = self.driver.create_node(name='test2',
+                                       image=image,
+                                       auth=rootPw,
+                                       ex_description='test2 node',
+                                       ex_network_domain='fakenetworkdomain',
+                                       ex_primary_nic_private_ipv4='10.0.0.1',
+                                       ex_is_started=False,
+                                       ex_ipv4_gateway='10.2.2.2')
+        self.assertEqual(node.id, 'e75ead52-692f-4314-8725-c8a4f4d13a87')
+        self.assertEqual(node.extra['status'].action, 'DEPLOY_SERVER')
+
+    def test_create_node_network_domain_no_vlan_no_ipv4_fail(self):
+        rootPw = NodeAuthPassword('pass123')
+        image = self.driver.list_images()[0]
+        with self.assertRaises(ValueError):
+            self.driver.create_node(name='test2',
+                                    image=image,
+                                    auth=rootPw,
+                                    ex_description='test2 node',
+                                    ex_network_domain='fake_network_domain',
+                                    ex_is_started=False)
+
+    def test_create_node_mcp2_additional_nics_legacy(self):
+        rootPw = NodeAuthPassword('pass123')
+        image = self.driver.list_images()[0]
+        additional_vlans = ['fakevlan1', 'fakevlan2']
+        additional_ipv4 = ['10.0.0.2', '10.0.0.3']
+        node = self.driver.create_node(
+            name='test2',
+            image=image,
+            auth=rootPw,
+            ex_description='test2 node',
+            ex_network_domain='fakenetworkdomain',
+            ex_primary_ipv4='10.0.0.1',
+            ex_additional_nics_vlan=additional_vlans,
+            ex_additional_nics_ipv4=additional_ipv4,
+            ex_is_started=False)
+        self.assertEqual(node.id, 'e75ead52-692f-4314-8725-c8a4f4d13a87')
+        self.assertEqual(node.extra['status'].action, 'DEPLOY_SERVER')
+
+    def test_create_node_bad_additional_nics_ipv4(self):
+        rootPw = NodeAuthPassword('pass123')
+        image = self.driver.list_images()[0]
+        with self.assertRaises(TypeError):
+            self.driver.create_node(name='test2',
+                                    image=image,
+                                    auth=rootPw,
+                                    ex_description='test2 node',
+                                    ex_network_domain='fake_network_domain',
+                                    ex_vlan='fake_vlan',
+                                    ex_additional_nics_ipv4='badstring',
+                                    ex_is_started=False)
+
+    def test_create_node_additional_nics(self):
+        root_pw = NodeAuthPassword('pass123')
+        image = self.driver.list_images()[0]
+        nic1 = DimensionDataNic(vlan='fake_vlan',
+                                network_adapter_name='v1000')
+        nic2 = DimensionDataNic(private_ip_v4='10.1.1.2',
+                                network_adapter_name='v1000')
+        additional_nics = [nic1, nic2]
+
+        node = self.driver.create_node(name='test2',
+                                       image=image,
+                                       auth=root_pw,
+                                       ex_description='test2 node',
+                                       ex_network_domain='fakenetworkdomain',
+                                       ex_primary_nic_private_ipv4='10.0.0.1',
+                                       ex_additional_nics=additional_nics,
+                                       ex_is_started=False)
+
+        self.assertEqual(node.id, 'e75ead52-692f-4314-8725-c8a4f4d13a87')
+        self.assertEqual(node.extra['status'].action, 'DEPLOY_SERVER')
+
+    def test_create_node_additional_nics_vlan_ipv4_coexist_fail(self):
+        root_pw = NodeAuthPassword('pass123')
+        image = self.driver.list_images()[0]
+        nic1 = DimensionDataNic(private_ip_v4='10.1.1.1', vlan='fake_vlan',
+                                network_adapter_name='v1000')
+        nic2 = DimensionDataNic(private_ip_v4='10.1.1.2', vlan='fake_vlan2',
+                                network_adapter_name='v1000')
+        additional_nics = [nic1, nic2]
+        with self.assertRaises(ValueError):
+            self.driver.create_node(name='test2',
+                                    image=image,
+                                    auth=root_pw,
+                                    ex_description='test2 node',
+                                    ex_network_domain='fakenetworkdomain',
+                                    ex_primary_nic_private_ipv4='10.0.0.1',
+                                    ex_additional_nics=additional_nics,
+                                    ex_is_started=False
+                                    )
+
+    def test_create_node_additional_nics_invalid_input_fail(self):
+        root_pw = NodeAuthPassword('pass123')
+        image = self.driver.list_images()[0]
+        additional_nics = 'blah'
+        with self.assertRaises(TypeError):
+            self.driver.create_node(name='test2',
+                                    image=image,
+                                    auth=root_pw,
+                                    ex_description='test2 node',
+                                    ex_network_domain='fakenetworkdomain',
+                                    ex_primary_nic_private_ipv4='10.0.0.1',
+                                    ex_additional_nics=additional_nics,
+                                    ex_is_started=False
+                                    )
+
+    def test_create_node_additional_nics_vlan_ipv4_not_exist_fail(self):
+        root_pw = NodeAuthPassword('pass123')
+        image = self.driver.list_images()[0]
+        nic1 = DimensionDataNic(network_adapter_name='v1000')
+        nic2 = DimensionDataNic(network_adapter_name='v1000')
+        additional_nics = [nic1, nic2]
+        with self.assertRaises(ValueError):
+            self.driver.create_node(name='test2',
+                                    image=image,
+                                    auth=root_pw,
+                                    ex_description='test2 node',
+                                    ex_network_domain='fakenetworkdomain',
+                                    ex_primary_nic_private_ipv4='10.0.0.1',
+                                    ex_additional_nics=additional_nics,
+                                    ex_is_started=False)
+
+    def test_create_node_bad_additional_nics_vlan(self):
+        rootPw = NodeAuthPassword('pass123')
+        image = self.driver.list_images()[0]
+        with self.assertRaises(TypeError):
+            self.driver.create_node(name='test2',
+                                    image=image,
+                                    auth=rootPw,
+                                    ex_description='test2 node',
+                                    ex_network_domain='fake_network_domain',
+                                    ex_vlan='fake_vlan',
+                                    ex_additional_nics_vlan='badstring',
+                                    ex_is_started=False)
+
+    def test_create_node_mcp2_indicate_dns(self):
+        rootPw = NodeAuthPassword('pass123')
+        image = self.driver.list_images()[0]
+        node = self.driver.create_node(name='test2',
+                                       image=image,
+                                       auth=rootPw,
+                                       ex_description='test node dns',
+                                       ex_network_domain='fakenetworkdomain',
+                                       ex_primary_ipv4='10.0.0.1',
+                                       ex_primary_dns='8.8.8.8',
+                                       ex_secondary_dns='8.8.4.4',
+                                       ex_is_started=False)
+        self.assertEqual(node.id, 'e75ead52-692f-4314-8725-c8a4f4d13a87')
+        self.assertEqual(node.extra['status'].action, 'DEPLOY_SERVER')
+
+    def test_ex_shutdown_graceful(self):
+        node = Node(id='11', name=None, state=None,
+                    public_ips=None, private_ips=None, driver=self.driver)
+        ret = self.driver.ex_shutdown_graceful(node)
+        self.assertTrue(ret is True)
+
+    def test_ex_shutdown_graceful_INPROGRESS(self):
+        DimensionDataMockHttp.type = 'INPROGRESS'
+        node = Node(id='11', name=None, state=None,
+                    public_ips=None, private_ips=None, driver=self.driver)
+        with self.assertRaises(DimensionDataAPIException):
+            self.driver.ex_shutdown_graceful(node)
+
+    def test_ex_start_node(self):
+        node = Node(id='11', name=None, state=None,
+                    public_ips=None, private_ips=None, driver=self.driver)
+        ret = self.driver.ex_start_node(node)
+        self.assertTrue(ret is True)
+
+    def test_ex_start_node_INPROGRESS(self):
+        DimensionDataMockHttp.type = 'INPROGRESS'
+        node = Node(id='11', name=None, state=None,
+                    public_ips=None, private_ips=None, driver=self.driver)
+        with self.assertRaises(DimensionDataAPIException):
+            self.driver.ex_start_node(node)
+
+    def test_ex_power_off(self):
+        node = Node(id='11', name=None, state=None,
+                    public_ips=None, private_ips=None, driver=self.driver)
+        ret = self.driver.ex_power_off(node)
+        self.assertTrue(ret is True)
+
+    def test_ex_update_vm_tools(self):
+        node = Node(id='11', name=None, state=None,
+                    public_ips=None, private_ips=None, driver=self.driver)
+        ret = self.driver.ex_update_vm_tools(node)
+        self.assertTrue(ret is True)
+
+    def test_ex_power_off_INPROGRESS(self):
+        DimensionDataMockHttp.type = 'INPROGRESS'
+        node = Node(id='11', name=None, state='STOPPING',
+                    public_ips=None, private_ips=None, driver=self.driver)
+
+        with self.assertRaises(DimensionDataAPIException):
+            self.driver.ex_power_off(node)
+
+    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_attach_node_to_vlan(self):
+        node = self.driver.ex_get_node_by_id('e75ead52-692f-4314-8725-c8a4f4d13a87')
+        vlan = self.driver.ex_get_vlan('0e56433f-d808-4669-821d-812769517ff8')
+        ret = self.driver.ex_attach_node_to_vlan(node, vlan)
+        self.assertTrue(ret is True)
+
+    def test_ex_destroy_nic(self):
+        node = self.driver.ex_destroy_nic('a202e51b-41c0-4cfc-add0-b1c62fc0ecf6')
+        self.assertTrue(node)
+
+    def test_list_networks(self):
+        nets = self.driver.list_networks()
+        self.assertEqual(nets[0].name, 'test-net1')
+        self.assertTrue(isinstance(nets[0].location, NodeLocation))
+
+    def test_ex_create_network(self):
+        location = self.driver.ex_get_location_by_id('NA9')
+        net = self.driver.ex_create_network(location, "Test Network", "test")
+        self.assertEqual(net.id, "208e3a8e-9d2f-11e2-b29c-001517c4643e")
+        self.assertEqual(net.name, "Test Network")
+
+    def test_ex_create_network_NO_DESCRIPTION(self):
+        location = self.driver.ex_get_location_by_id('NA9')
+        net = self.driver.ex_create_network(location, "Test Network")
+        self.assertEqual(net.id, "208e3a8e-9d2f-11e2-b29c-001517c4643e")
+        self.assertEqual(net.name, "Test Network")
+
+    def test_ex_delete_network(self):
+        net = self.driver.ex_list_networks()[0]
+        result = self.driver.ex_delete_network(net)
+        self.assertTrue(result)
+
+    def test_ex_rename_network(self):
+        net = self.driver.ex_list_networks()[0]
+        result = self.driver.ex_rename_network(net, "barry")
+        self.assertTrue(result)
+
+    def test_ex_create_network_domain(self):
+        location = self.driver.ex_get_location_by_id('NA9')
+        plan = NetworkDomainServicePlan.ADVANCED
+        net = self.driver.ex_create_network_domain(location=location,
+                                                   name='test',
+                                                   description='test',
+                                                   service_plan=plan)
+        self.assertEqual(net.name, 'test')
+        self.assertTrue(net.id, 'f14a871f-9a25-470c-aef8-51e13202e1aa')
+
+    def test_ex_create_network_domain_NO_DESCRIPTION(self):
+        location = self.driver.ex_get_location_by_id('NA9')
+        plan = NetworkDomainServicePlan.ADVANCED
+        net = self.driver.ex_create_network_domain(location=location,
+                                                   name='test',
+                                                   service_plan=plan)
+        self.assertEqual(net.name, 'test')
+        self.assertTrue(net.id, 'f14a871f-9a25-470c-aef8-51e13202e1aa')
+
+    def test_ex_get_network_domain(self):
+        net = self.driver.ex_get_network_domain('8cdfd607-f429-4df6-9352-162cfc0891be')
+        self.assertEqual(net.id, '8cdfd607-f429-4df6-9352-162cfc0891be')
+        self.assertEqual(net.description, 'test2')
+        self.assertEqual(net.name, 'test')
+
+    def test_ex_update_network_domain(self):
+        net = self.driver.ex_get_network_domain('8cdfd607-f429-4df6-9352-162cfc0891be')
+        net.name = 'new name'
+        net2 = self.driver.ex_update_network_domain(net)
+        self.assertEqual(net2.name, 'new name')
+
+    def test_ex_delete_network_domain(self):
+        net = self.driver.ex_get_network_domain('8cdfd607-f429-4df6-9352-162cfc0891be')
+        result = self.driver.ex_delete_network_domain(net)
+        self.assertTrue(result)
+
+    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, 'Aurora')
+        self.assertTrue(isinstance(nets[0].location, NodeLocation))
+
+    def test_ex_list_network_domains_ALLFILTERS(self):
+        DimensionDataMockHttp.type = 'ALLFILTERS'
+        nets = self.driver.ex_list_network_domains(location='fake_location', name='fake_name',
+                                                   service_plan='fake_plan', state='fake_state')
+        self.assertEqual(nets[0].name, 'Aurora')
+        self.assertTrue(isinstance(nets[0].location, NodeLocation))
+
+    def test_ex_list_vlans(self):
+        vlans = self.driver.ex_list_vlans()
+        self.assertEqual(vlans[0].name, "Primary")
+
+    def test_ex_list_vlans_ALLFILTERS(self):
+        DimensionDataMockHttp.type = 'ALLFILTERS'
+        vlans = self.driver.ex_list_vlans(location='fake_location', network_domain='fake_network_domain',
+                                          name='fake_name', ipv4_address='fake_ipv4', ipv6_address='fake_ipv6', state='fake_state')
+        self.assertEqual(vlans[0].name, "Primary")
+
+    def test_ex_create_vlan(self,):
+        net = self.driver.ex_get_network_domain('8cdfd607-f429-4df6-9352-162cfc0891be')
+        vlan = self.driver.ex_create_vlan(network_domain=net,
+                                          name='test',
+                                          private_ipv4_base_address='10.3.4.0',
+                                          private_ipv4_prefix_size='24',
+                                          description='test vlan')
+        self.assertEqual(vlan.id, '0e56433f-d808-4669-821d-812769517ff8')
+
+    def test_ex_create_vlan_NO_DESCRIPTION(self,):
+        net = self.driver.ex_get_network_domain('8cdfd607-f429-4df6-9352-162cfc0891be')
+        vlan = self.driver.ex_create_vlan(network_domain=net,
+                                          name='test',
+                                          private_ipv4_base_address='10.3.4.0',
+                                          private_ipv4_prefix_size='24')
+        self.assertEqual(vlan.id, '0e56433f-d808-4669-821d-812769517ff8')
+
+    def test_ex_get_vlan(self):
+        vlan = self.driver.ex_get_vlan('0e56433f-d808-4669-821d-812769517ff8')
+        self.assertEqual(vlan.id, '0e56433f-d808-4669-821d-812769517ff8')
+        self.assertEqual(vlan.description, 'test2')
+        self.assertEqual(vlan.status, 'NORMAL')
+        self.assertEqual(vlan.name, 'Production VLAN')
+        self.assertEqual(vlan.private_ipv4_range_address, '10.0.3.0')
+        self.assertEqual(vlan.private_ipv4_range_size, 24)
+        self.assertEqual(vlan.ipv6_range_size, 64)
+        self.assertEqual(vlan.ipv6_range_address, '2607:f480:1111:1153:0:0:0:0')
+        self.assertEqual(vlan.ipv4_gateway, '10.0.3.1')
+        self.assertEqual(vlan.ipv6_gateway, '2607:f480:1111:1153:0:0:0:1')
+
+    def test_ex_wait_for_state(self):
+        self.driver.ex_wait_for_state('NORMAL',
+                                      self.driver.ex_get_vlan,
+                                      vlan_id='0e56433f-d808-4669-821d-812769517ff8')
+
+    def test_ex_wait_for_state_NODE(self):
+        self.driver.ex_wait_for_state('running',
+                                      self.driver.ex_get_node_by_id,
+                                      id='e75ead52-692f-4314-8725-c8a4f4d13a87')
+
+    def test_ex_wait_for_state_FAIL(self):
+        with self.assertRaises(DimensionDataAPIException) as context:
+            self.driver.ex_wait_for_state('starting',
+                                          self.driver.ex_get_node_by_id,
+                                          id='e75ead52-692f-4314-8725-c8a4f4d13a87',
+                                          timeout=2
+                                          )
+        self.assertEqual(context.exception.code, 'running')
+        self.assertTrue('timed out' in context.exception.msg)
+
+    def test_ex_update_vlan(self):
+        vlan = self.driver.ex_get_vlan('0e56433f-d808-4669-821d-812769517ff8')
+        vlan.name = 'new name'
+        vlan2 = self.driver.ex_update_vlan(vlan)
+        self.assertEqual(vlan2.name, 'new name')
+
+    def test_ex_delete_vlan(self):
+        vlan = self.driver.ex_get_vlan('0e56433f-d808-4669-821d-812769517ff8')
+        result = self.driver.ex_delete_vlan(vlan)
+        self.assertTrue(result)
+
+    def test_ex_expand_vlan(self):
+        vlan = self.driver.ex_get_vlan('0e56433f-d808-4669-821d-812769517ff8')
+        vlan.private_ipv4_range_size = '23'
+        vlan = self.driver.ex_expand_vlan(vlan)
+        self.assertEqual(vlan.private_ipv4_range_size, '23')
+
+    def test_ex_add_public_ip_block_to_network_domain(self):
+        net = self.driver.ex_get_network_domain('8cdfd607-f429-4df6-9352-162cfc0891be')
+        block = self.driver.ex_add_public_ip_block_to_network_domain(net)
+        self.assertEqual(block.id, '9945dc4a-bdce-11e4-8c14-b8ca3a5d9ef8')
+
+    def test_ex_list_public_ip_blocks(self):
+        net = self.driver.ex_get_network_domain('8cdfd607-f429-4df6-9352-162cfc0891be')
+        blocks = self.driver.ex_list_public_ip_blocks(net)
+        self.assertEqual(blocks[0].base_ip, '168.128.4.18')
+        self.assertEqual(blocks[0].size, '2')
+        self.assertEqual(blocks[0].id, '9945dc4a-bdce-11e4-8c14-b8ca3a5d9ef8')
+        self.assertEqual(blocks[0].location.id, 'NA9')
+        self.assertEqual(blocks[0].network_domain.id, net.id)
+
+    def test_ex_get_public_ip_block(self):
+        net = self.driver.ex_get_network_domain('8cdfd607-f429-4df6-9352-162cfc0891be')
+        block = self.driver.ex_get_public_ip_block('9945dc4a-bdce-11e4-8c14-b8ca3a5d9ef8')
+        self.assertEqual(block.base_ip, '168.128.4.18')
+        self.assertEqual(block.size, '2')
+        self.assertEqual(block.id, '9945dc4a-bdce-11e4-8c14-b8ca3a5d9ef8')
+        self.assertEqual(block.location.id, 'NA9')
+        self.assertEqual(block.network_domain.id, net.id)
+
+    def test_ex_delete_public_ip_block(self):
+        block = self.driver.ex_get_public_ip_block('9945dc4a-bdce-11e4-8c14-b8ca3a5d9ef8')
+        result = self.driver.ex_delete_public_ip_block(block)
+        self.assertTrue(result)
+
+    def test_ex_list_firewall_rules(self):
+        net = self.driver.ex_get_network_domain('8cdfd607-f429-4df6-9352-162cfc0891be')
+        rules = self.driver.ex_list_firewall_rules(net)
+        self.assertEqual(rules[0].id, '756cba02-b0bc-48f4-aea5-9445870b6148')
+        self.assertEqual(rules[0].network_domain.id, '8cdfd607-f429-4df6-9352-162cfc0891be')
+        self.assertEqual(rules[0].name, 'CCDEFAULT.BlockOutboundMailIPv4')
+        self.assertEqual(rules[0].action, 'DROP')
+        self.assertEqual(rules[0].ip_version, 'IPV4')
+        self.assertEqual(rules[0].protocol, 'TCP')
+        self.assertEqual(rules[0].source.ip_address, 'ANY')
+        self.assertTrue(rules[0].source.any_ip)
+        self.assertTrue(rules[0].destination.any_ip)
+
+    def test_ex_create_firewall_rule(self):
+        net = self.driver.ex_get_network_domain('8cdfd607-f429-4df6-9352-162cfc0891be')
+        rules = self.driver.ex_list_firewall_rules(net)
+        rule = self.driver.ex_create_firewall_rule(net, rules[0], 'FIRST')
+        self.assertEqual(rule.id, 'd0a20f59-77b9-4f28-a63b-e58496b73a6c')
+
+    def test_ex_create_firewall_rule_with_specific_source_ip(self):
+        net = self.driver.ex_get_network_domain('8cdfd607-f429-4df6-9352-162cfc0891be')
+        rules = self.driver.ex_list_firewall_rules(net)
+        specific_source_ip_rule = list(filter(lambda x: x.name == 'SpecificSourceIP',
+                                              rules))[0]
+        rule = self.driver.ex_create_firewall_rule(net, specific_source_ip_rule, 'FIRST')
+        self.assertEqual(rule.id, 'd0a20f59-77b9-4f28-a63b-e58496b73a6c')
+
+    def test_ex_create_firewall_rule_with_source_ip(self):
+        net = self.driver.ex_get_network_domain(
+            '8cdfd607-f429-4df6-9352-162cfc0891be')
+        rules = self.driver.ex_list_firewall_rules(net)
+        specific_source_ip_rule = \
+            list(filter(lambda x: x.name == 'SpecificSourceIP',
+                        rules))[0]
+        specific_source_ip_rule.source.any_ip = False
+        specific_source_ip_rule.source.ip_address = '10.0.0.1'
+        specific_source_ip_rule.source.ip_prefix_size = '15'
+        rule = self.driver.ex_create_firewall_rule(net,
+                                                   specific_source_ip_rule,
+                                                   'FIRST')
+        self.assertEqual(rule.id, 'd0a20f59-77b9-4f28-a63b-e58496b73a6c')
+
+    def test_ex_create_firewall_rule_with_any_ip(self):
+        net = self.driver.ex_get_network_domain(
+            '8cdfd607-f429-4df6-9352-162cfc0891be')
+        rules = self.driver.ex_list_firewall_rules(net)
+        specific_source_ip_rule = \
+            list(filter(lambda x: x.name == 'SpecificSourceIP',
+                        rules))[0]
+        specific_source_ip_rule.source.any_ip = True
+        rule = self.driver.ex_create_firewall_rule(net,
+                                                   specific_source_ip_rule,
+                                                   'FIRST')
+        self.assertEqual(rule.id, 'd0a20f59-77b9-4f28-a63b-e58496b73a6c')
+
+    def test_ex_create_firewall_rule_ip_prefix_size(self):
+        net = self.driver.ex_get_network_domain(
+            '8cdfd607-f429-4df6-9352-162cfc0891be')
+        rule = self.driver.ex_list_firewall_rules(net)[0]
+        rule.source.address_list_id = None
+        rule.source.any_ip = False
+        rule.source.ip_address = '10.2.1.1'
+        rule.source.ip_prefix_size = '10'
+        rule.destination.address_list_id = None
+        rule.destination.any_ip = False
+        rule.destination.ip_address = '10.0.0.1'
+        rule.destination.ip_prefix_size = '20'
+        self.driver.ex_create_firewall_rule(net, rule, 'LAST')
+
+    def test_ex_create_firewall_rule_address_list(self):
+        net = self.driver.ex_get_network_domain('8cdfd607-f429-4df6-9352-162cfc0891be')
+        rule = self.driver.ex_list_firewall_rules(net)[0]
+        rule.source.address_list_id = '12345'
+        rule.destination.address_list_id = '12345'
+        self.driver.ex_create_firewall_rule(net, rule, 'LAST')
+
+    def test_ex_create_firewall_rule_port_list(self):
+        net = self.driver.ex_get_network_domain('8cdfd607-f429-4df6-9352-162cfc0891be')
+        rule = self.driver.ex_list_firewall_rules(net)[0]
+        rule.source.port_list_id = '12345'
+        rule.destination.port_list_id = '12345'
+        self.driver.ex_create_firewall_rule(net, rule, 'LAST')
+
+    def test_ex_create_firewall_rule_port(self):
+        net = self.driver.ex_get_network_domain(
+            '8cdfd607-f429-4df6-9352-162cfc0891be')
+        rule = self.driver.ex_list_firewall_rules(net)[0]
+        rule.source.port_list_id = None
+        rule.source.port_begin = '8000'
+        rule.source.port_end = '8005'
+        rule.destination.port_list_id = None
+        rule.destination.port_begin = '7000'
+        rule.destination.port_end = '7005'
+        self.driver.ex_create_firewall_rule(net, rule, 'LAST')
+
+    def test_ex_create_firewall_rule_ALL_VALUES(self):
+        net = self.driver.ex_get_network_domain('8cdfd607-f429-4df6-9352-162cfc0891be')
+        rules = self.driver.ex_list_firewall_rules(net)
+        for rule in rules:
+            self.driver.ex_create_firewall_rule(net, rule, 'LAST')
+
+    def test_ex_create_firewall_rule_WITH_POSITION_RULE(self):
+        net = self.driver.ex_get_network_domain('8cdfd607-f429-4df6-9352-162cfc0891be')
+        rules = self.driver.ex_list_firewall_rules(net)
+        rule = self.driver.ex_create_firewall_rule(net, rules[-2], 'BEFORE', rules[-1])
+        self.assertEqual(rule.id, 'd0a20f59-77b9-4f28-a63b-e58496b73a6c')
+
+    def test_ex_create_firewall_rule_WITH_POSITION_RULE_STR(self):
+        net = self.driver.ex_get_network_domain('8cdfd607-f429-4df6-9352-162cfc0891be')
+        rules = self.driver.ex_list_firewall_rules(net)
+        rule = self.driver.ex_create_firewall_rule(net, rules[-2], 'BEFORE', 'RULE_WITH_SOURCE_AND_DEST')
+        self.assertEqual(rule.id, 'd0a20f59-77b9-4f28-a63b-e58496b73a6c')
+
+    def test_ex_create_firewall_rule_FAIL_POSITION(self):
+        net = self.driver.ex_get_network_domain('8cdfd607-f429-4df6-9352-162cfc0891be')
+        rules = self.driver.ex_list_firewall_rules(net)
+        with self.assertRaises(ValueError):
+            self.driver.ex_create_firewall_rule(net, rules[0], 'BEFORE')
+
+    def test_ex_create_firewall_rule_FAIL_POSITION_WITH_RULE(self):
+        net = self.driver.ex_get_network_domain('8cdfd607-f429-4df6-9352-162cfc0891be')
+        rules = self.driver.ex_list_firewall_rules(net)
+        with self.assertRaises(ValueError):
+            self.driver.ex_create_firewall_rule(net, rules[0], 'LAST', 'RULE_WITH_SOURCE_AND_DEST')
+
+    def test_ex_get_firewall_rule(self):
+        net = self.driver.ex_get_network_domain('8cdfd607-f429-4df6-9352-162cfc0891be')
+        rule = self.driver.ex_get_firewall_rule(net, 'd0a20f59-77b9-4f28-a63b-e58496b73a6c')
+        self.assertEqual(rule.id, 'd0a20f59-77b9-4f28-a63b-e58496b73a6c')
+
+    def test_ex_set_firewall_rule_state(self):
+        net = self.driver.ex_get_network_domain('8cdfd607-f429-4df6-9352-162cfc0891be')
+        rule = self.driver.ex_get_firewall_rule(net, 'd0a20f59-77b9-4f28-a63b-e58496b73a6c')
+        result = self.driver.ex_set_firewall_rule_state(rule, False)
+        self.assertTrue(result)
+
+    def test_ex_delete_firewall_rule(self):
+        net = self.driver.ex_get_network_domain('8cdfd607-f429-4df6-9352-162cfc0891be')
+        rule = self.driver.ex_get_firewall_rule(net, 'd0a20f59-77b9-4f28-a63b-e58496b73a6c')
+        result = self.driver.ex_delete_firewall_rule(rule)
+        self.assertTrue(result)
+
+    def test_ex_edit_firewall_rule(self):
+        net = self.driver.ex_get_network_domain(
+            '8cdfd607-f429-4df6-9352-162cfc0891be')
+        rule = self.driver.ex_get_firewall_rule(
+            net, 'd0a20f59-77b9-4f28-a63b-e58496b73a6c')
+        rule.source.any_ip = True
+        result = self.driver.ex_edit_firewall_rule(rule=rule, position='LAST')
+        self.assertTrue(result)
+
+    def test_ex_edit_firewall_rule_source_ipaddresslist(self):
+        net = self.driver.ex_get_network_domain(
+            '8cdfd607-f429-4df6-9352-162cfc0891be')
+        rule = self.driver.ex_get_firewall_rule(
+            net, 'd0a20f59-77b9-4f28-a63b-e58496b73a6c')
+        rule.source.address_list_id = '802abc9f-45a7-4efb-9d5a-810082368222'
+        rule.source.any_ip = False
+        rule.source.ip_address = '10.0.0.1'
+        rule.source.ip_prefix_size = 10
+        result = self.driver.ex_edit_firewall_rule(rule=rule, position='LAST')
+        self.assertTrue(result)
+
+    def test_ex_edit_firewall_rule_destination_ipaddresslist(self):
+        net = self.driver.ex_get_network_domain(
+            '8cdfd607-f429-4df6-9352-162cfc0891be')
+        rule = self.driver.ex_get_firewall_rule(
+            net, 'd0a20f59-77b9-4f28-a63b-e58496b73a6c')
+        rule.destination.address_list_id = '802abc9f-45a7-4efb-9d5a-810082368222'
+        rule.destination.any_ip = False
+        rule.destination.ip_address = '10.0.0.1'
+        rule.destination.ip_prefix_size = 10
+        result = self.driver.ex_edit_firewall_rule(rule=rule, position='LAST')
+        self.assertTrue(result)
+
+    def test_ex_edit_firewall_rule_destination_ipaddress(self):
+        net = self.driver.ex_get_network_domain(
+            '8cdfd607-f429-4df6-9352-162cfc0891be')
+        rule = self.driver.ex_get_firewall_rule(
+            net, 'd0a20f59-77b9-4f28-a63b-e58496b73a6c')
+        rule.source.address_list_id = None
+        rule.source.any_ip = False
+        rule.source.ip_address = '10.0.0.1'
+        rule.source.ip_prefix_size = '10'
+        result = self.driver.ex_edit_firewall_rule(rule=rule, position='LAST')
+        self.assertTrue(result)
+
+    def test_ex_edit_firewall_rule_source_ipaddress(self):
+        net = self.driver.ex_get_network_domain(
+            '8cdfd607-f429-4df6-9352-162cfc0891be')
+        rule = self.driver.ex_get_firewall_rule(
+            net, 'd0a20f59-77b9-4f28-a63b-e58496b73a6c')
+        rule.destination.address_list_id = None
+        rule.destination.any_ip = False
+        rule.destination.ip_address = '10.0.0.1'
+        rule.destination.ip_prefix_size = '10'
+        result = self.driver.ex_edit_firewall_rule(rule=rule, position='LAST')
+        self.assertTrue(result)
+
+    def test_ex_edit_firewall_rule_with_relative_rule(self):
+        net = self.driver.ex_get_network_domain(
+            '8cdfd607-f429-4df6-9352-162cfc0891be')
+        rule = self.driver.ex_get_firewall_rule(
+            net, 'd0a20f59-77b9-4f28-a63b-e58496b73a6c')
+        placement_rule = self.driver.ex_list_firewall_rules(
+            network_domain=net)[-1]
+        result = self.driver.ex_edit_firewall_rule(
+            rule=rule, position='BEFORE',
+            relative_rule_for_position=placement_rule)
+        self.assertTrue(result)
+
+    def test_ex_edit_firewall_rule_with_relative_rule_by_name(self):
+        net = self.driver.ex_get_network_domain(
+            '8cdfd607-f429-4df6-9352-162cfc0891be')
+        rule = self.driver.ex_get_firewall_rule(
+            net, 'd0a20f59-77b9-4f28-a63b-e58496b73a6c')
+        placement_rule = self.driver.ex_list_firewall_rules(
+            network_domain=net)[-1]
+        result = self.driver.ex_edit_firewall_rule(
+            rule=rule, position='BEFORE',
+            relative_rule_for_position=placement_rule.name)
+        self.assertTrue(result)
+
+    def test_ex_edit_firewall_rule_source_portlist(self):
+        net = self.driver.ex_get_network_domain(
+            '8cdfd607-f429-4df6-9352-162cfc0891be')
+        rule = self.driver.ex_get_firewall_rule(
+            net, 'd0a20f59-77b9-4f28-a63b-e58496b73a6c')
+        rule.source.port_list_id = '802abc9f-45a7-4efb-9d5a-810082368222'
+        result = self.driver.ex_edit_firewall_rule(rule=rule, position='LAST')
+        self.assertTrue(result)
+
+    def test_ex_edit_firewall_rule_source_port(self):
+        net = self.driver.ex_get_network_domain(
+            '8cdfd607-f429-4df6-9352-162cfc0891be')
+        rule = self.driver.ex_get_firewall_rule(
+            net, 'd0a20f59-77b9-4f28-a63b-e58496b73a6c')
+        rule.source.port_list_id = None
+        rule.source.port_begin = '3'
+        rule.source.port_end = '10'
+        result = self.driver.ex_edit_firewall_rule(rule=rule, position='LAST')
+        self.assertTrue(result)
+
+    def test_ex_edit_firewall_rule_destination_portlist(self):
+        net = self.driver.ex_get_network_domain(
+            '8cdfd607-f429-4df6-9352-162cfc0891be')
+        rule = self.driver.ex_get_firewall_rule(
+            net, 'd0a20f59-77b9-4f28-a63b-e58496b73a6c')
+        rule.destination.port_list_id = '802abc9f-45a7-4efb-9d5a-810082368222'
+        result = self.driver.ex_edit_firewall_rule(rule=rule, position='LAST')
+        self.assertTrue(result)
+
+    def test_ex_edit_firewall_rule_destination_port(self):
+        net = self.driver.ex_get_network_domain(
+            '8cdfd607-f429-4df6-9352-162cfc0891be')
+        rule = self.driver.ex_get_firewall_rule(
+            net, 'd0a20f59-77b9-4f28-a63b-e58496b73a6c')
+        rule.destination.port_list_id = None
+        rule.destination.port_begin = '3'
+        rule.destination.port_end = '10'
+        result = self.driver.ex_edit_firewall_rule(rule=rule, position='LAST')
+        self.assertTrue(result)
+
+    def test_ex_edit_firewall_rule_invalid_position_fail(self):
+        net = self.driver.ex_get_network_domain(
+            '8cdfd607-f429-4df6-9352-162cfc0891be')
+        rule = self.driver.ex_get_firewall_rule(
+            net, 'd0a20f59-77b9-4f28-a63b-e58496b73a6c')
+        with self.assertRaises(ValueError):
+            self.driver.ex_edit_firewall_rule(rule=rule, position='BEFORE')
+
+    def test_ex_edit_firewall_rule_invalid_position_relative_rule_fail(self):
+        net = self.driver.ex_get_network_domain(
+            '8cdfd607-f429-4df6-9352-162cfc0891be')
+        rule = self.driver.ex_get_firewall_rule(
+            net, 'd0a20f59-77b9-4f28-a63b-e58496b73a6c')
+        relative_rule = self.driver.ex_list_firewall_rules(
+            network_domain=net)[-1]
+        with self.assertRaises(ValueError):
+            self.driver.ex_edit_firewall_rule(rule=rule, position='FIRST',
+                                              relative_rule_for_position=relative_rule)
+
+    def test_ex_create_nat_rule(self):
+        net = self.driver.ex_get_network_domain('8cdfd607-f429-4df6-9352-162cfc0891be')
+        rule = self.driver.ex_create_nat_rule(net, '1.2.3.4', '4.3.2.1')
+        self.assertEqual(rule.id, 'd31c2db0-be6b-4d50-8744-9a7a534b5fba')
+
+    def test_ex_list_nat_rules(self):
+        net = self.driver.ex_get_network_domain('8cdfd607-f429-4df6-9352-162cfc0891be')
+        rules = self.driver.ex_list_nat_rules(net)
+        self.assertEqual(rules[0].id, '2187a636-7ebb-49a1-a2ff-5d617f496dce')
+        self.assertEqual(rules[0].internal_ip, '10.0.0.15')
+        self.assertEqual(rules[0].external_ip, '165.180.12.18')
+
+    def test_ex_get_nat_rule(self):
+        net = self.driver.ex_get_network_domain('8cdfd607-f429-4df6-9352-162cfc0891be')
+        rule = self.driver.ex_get_nat_rule(net, '2187a636-7ebb-49a1-a2ff-5d617f496dce')
+        self.assertEqual(rule.id, '2187a636-7ebb-49a1-a2ff-5d617f496dce')
+        self.assertEqual(rule.internal_ip, '10.0.0.16')
+        self.assertEqual(rule.external_ip, '165.180.12.19')
+
+    def test_ex_delete_nat_rule(self):
+        net = self.driver.ex_get_network_domain('8cdfd607-f429-4df6-9352-162cfc0891be')
+        rule = self.driver.ex_get_nat_rule(net, '2187a636-7ebb-49a1-a2ff-5d617f496dce')
+        result = self.driver.ex_delete_nat_rule(rule)
+        self.assertTrue(result)
+
+    def test_ex_enable_monitoring(self):
+        node = self.driver.list_nodes()[0]
+        result = self.driver.ex_enable_monitoring(node, "ADVANCED")
+        self.assertTrue(result)
+
+    def test_ex_disable_monitoring(self):
+        node = self.driver.list_nodes()[0]
+        result = self.driver.ex_disable_monitoring(node)
+        self.assertTrue(result)
+
+    def test_ex_change_monitoring_plan(self):
+        node = self.driver.list_nodes()[0]
+        result = self.driver.ex_update_monitoring_plan(node, "ESSENTIALS")
+        self.assertTrue(result)
+
+    def test_ex_add_storage_to_node(self):
+        node = self.driver.list_nodes()[0]
+        result = self.driver.ex_add_storage_to_node(node, 30, 'PERFORMANCE')
+        self.assertTrue(result)
+
+    def test_ex_remove_storage_from_node(self):
+        node = self.driver.list_nodes()[0]
+        result = self.driver.ex_remove_storage_from_node(node, 0)
+        self.assertTrue(result)
+
+    def test_ex_change_storage_speed(self):
+        node = self.driver.list_nodes()[0]
+        result = self.driver.ex_change_storage_speed(node, 1, 'PERFORMANCE')
+        self.assertTrue(result)
+
+    def test_ex_change_storage_size(self):
+        node = self.driver.list_nodes()[0]
+        result = self.driver.ex_change_storage_size(node, 1, 100)
+        self.assertTrue(result)
+
+    def test_ex_clone_node_to_image(self):
+        node = self.driver.list_nodes()[0]
+        result = self.driver.ex_clone_node_to_image(node, 'my image', 'a description')
+        self.assertTrue(result)
+
+    def test_ex_update_node(self):
+        node = self.driver.list_nodes()[0]
+        result = self.driver.ex_update_node(node, 'my new name', 'a description', 2, 4048)
+        self.assertTrue(result)
+
+    def test_ex_reconfigure_node(self):
+        node = self.driver.list_nodes()[0]
+        result = self.driver.ex_reconfigure_node(node, 4, 4, 1, 'HIGHPERFORMANCE')
+        self.assertTrue(result)
+
+    def test_ex_get_location_by_id(self):
+        location = self.driver.ex_get_location_by_id('NA9')
+        self.assertTrue(location.id, 'NA9')
+
+    def test_ex_get_location_by_id_NO_LOCATION(self):
+        location = self.driver.ex_get_location_by_id(None)
+        self.assertIsNone(location)
+
+    def test_ex_get_base_image_by_id(self):
+        image_id = self.driver.list_images()[0].id
+        image = self.driver.ex_get_base_image_by_id(image_id)
+        self.assertEqual(image.extra['OS_type'], 'UNIX')
+
+    def test_ex_get_customer_image_by_id(self):
+        image_id = self.driver.ex_list_customer_images()[1].id
+        image = self.driver.ex_get_customer_image_by_id(image_id)
+        self.assertEqual(image.extra['OS_type'], 'WINDOWS')
+
+    def test_ex_get_image_by_id_base_img(self):
+        image_id = self.driver.list_images()[1].id
+        image = self.driver.ex_get_base_image_by_id(image_id)
+        self.assertEqual(image.extra['OS_type'], 'WINDOWS')
+
+    def test_ex_get_image_by_id_customer_img(self):
+        image_id = self.driver.ex_list_customer_images()[0].id
+        image = self.driver.ex_get_customer_image_by_id(image_id)
+        self.assertEqual(image.extra['OS_type'], 'UNIX')
+
+    def test_ex_get_image_by_id_customer_FAIL(self):
+        image_id = 'FAKE_IMAGE_ID'
+        with self.assertRaises(DimensionDataAPIException):
+            self.driver.ex_get_base_image_by_id(image_id)
+
+    def test_ex_create_anti_affinity_rule(self):
+        node_list = self.driver.list_nodes()
+        success = self.driver.ex_create_anti_affinity_rule([node_list[0], node_list[1]])
+        self.assertTrue(success)
+
+    def test_ex_create_anti_affinity_rule_TUPLE(self):
+        node_list = self.driver.list_nodes()
+        success = self.driver.ex_create_anti_affinity_rule((node_list[0], node_list[1]))
+        self.assertTrue(success)
+
+    def test_ex_create_anti_affinity_rule_TUPLE_STR(self):
+        node_list = self.driver.list_nodes()
+        success = self.driver.ex_create_anti_affinity_rule((node_list[0].id, node_list[1].id))
+        self.assertTrue(success)
+
+    def test_ex_create_anti_affinity_rule_FAIL_STR(self):
+        node_list = 'string'
+        with self.assertRaises(TypeError):
+            self.driver.ex_create_anti_affinity_rule(node_list)
+
+    def test_ex_create_anti_affinity_rule_FAIL_EXISTING(self):
+        node_list = self.driver.list_nodes()
+        DimensionDataMockHttp.type = 'FAIL_EXISTING'
+        with self.assertRaises(DimensionDataAPIException):
+            self.driver.ex_create_anti_affinity_rule((node_list[0], node_list[1]))
+
+    def test_ex_delete_anti_affinity_rule(self):
+        net_domain = self.driver.ex_list_network_domains()[0]
+        rule = self.driver.ex_list_anti_affinity_rules(network_domain=net_domain)[0]
+        success = self.driver.ex_delete_anti_affinity_rule(rule)
+        self.assertTrue(success)
+
+    def test_ex_delete_anti_affinity_rule_STR(self):
+        net_domain = self.driver.ex_list_network_domains()[0]
+        rule = self.driver.ex_list_anti_affinity_rules(network_domain=net_domain)[0]
+        success = self.driver.ex_delete_anti_affinity_rule(rule.id)
+        self.assertTrue(success)
+
+    def test_ex_delete_anti_affinity_rule_FAIL(self):
+        net_domain = self.driver.ex_list_network_domains()[0]
+        rule = self.driver.ex_list_anti_affinity_rules(network_domain=net_domain)[0]
+        DimensionDataMockHttp.type = 'FAIL'
+        with self.assertRaises(DimensionDataAPIException):
+            self.driver.ex_delete_anti_affinity_rule(rule)
+
+    def test_ex_list_anti_affinity_rules_NETWORK_DOMAIN(self):
+        net_domain = self.driver.ex_list_network_domains()[0]
+        rules = self.driver.ex_list_anti_affinity_rules(network_domain=net_domain)
+        self.assertTrue(isinstance(rules, list))
+        self.assertEqual(len(rules), 2)
+        self.assertTrue(isinstance(rules[0].id, str))
+        self.assertTrue(isinstance(rules[0].node_list, list))
+
+    def test_ex_list_anti_affinity_rules_NETWORK(self):
+        network = self.driver.list_networks()[0]
+        rules = self.driver.ex_list_anti_affinity_rules(network=network)
+        self.assertTrue(isinstance(rules, list))
+        self.assertEqual(len(rules), 2)
+        self.assertTrue(isinstance(rules[0].id, str))
+        self.assertTrue(isinstance(rules[0].node_list, list))
+
+    def test_ex_list_anti_affinity_rules_NODE(self):
+        node = self.driver.list_nodes()[0]
+        rules = self.driver.ex_list_anti_affinity_rules(node=node)
+        self.assertTrue(isinstance(rules, list))
+        self.assertEqual(len(rules), 2)
+        self.assertTrue(isinstance(rules[0].id, str))
+        self.assertTrue(isinstance(rules[0].node_list, list))
+
+    def test_ex_list_anti_affinity_rules_PAGINATED(self):
+        net_domain = self.driver.ex_list_network_domains()[0]
+        DimensionDataMockHttp.type = 'PAGINATED'
+        rules = self.driver.ex_list_anti_affinity_rules(network_domain=net_domain)
+        self.assertTrue(isinstance(rules, list))
+        self.assertEqual(len(rules), 4)
+        self.assertTrue(isinstance(rules[0].id, str))
+        self.assertTrue(isinstance(rules[0].node_list, list))
+
+    def test_ex_list_anti_affinity_rules_ALLFILTERS(self):
+        net_domain = self.driver.ex_list_network_domains()[0]
+        DimensionDataMockHttp.type = 'ALLFILTERS'
+        rules = self.driver.ex_list_anti_affinity_rules(network_domain=net_domain, filter_id='FAKE_ID', filter_state='FAKE_STATE')
+        self.assertTrue(isinstance(rules, list))
+        self.assertEqual(len(rules), 2)
+        self.assertTrue(isinstance(rules[0].id, str))
+        self.assertTrue(isinstance(rules[0].node_list, list))
+
+    def test_ex_list_anti_affinity_rules_BAD_ARGS(self):
+        with self.assertRaises(ValueError):
+            self.driver.ex_list_anti_affinity_rules(network='fake_network', network_domain='fake_network_domain')
+
+    def test_ex_create_tag_key(self):
+        success = self.driver.ex_create_tag_key('MyTestKey')
+        self.assertTrue(success)
+
+    def test_ex_create_tag_key_ALLPARAMS(self):
+        self.driver.connection._get_orgId()
+        DimensionDataMockHttp.type = 'ALLPARAMS'
+        success = self.driver.ex_create_tag_key('MyTestKey', description="Test Key Desc.", value_required=False, display_on_report=False)
+        self.assertTrue(success)
+
+    def test_ex_create_tag_key_BADREQUEST(self):
+        self.driver.connection._get_orgId()
+        DimensionDataMockHttp.type = 'BADREQUEST'
+        with self.assertRaises(DimensionDataAPIException):
+            self.driver.ex_create_tag_key('MyTestKey')
+
+    def test_ex_list_tag_keys(self):
+        tag_keys = self.driver.ex_list_tag_keys()
+        self.assertTrue(isinstance(tag_keys, list))
+        self.assertTrue(isinstance(tag_keys[0], DimensionDataTagKey))
+        self.assertTrue(isinstance(tag_keys[0].id, str))
+
+    def test_ex_list_tag_keys_ALLFILTERS(self):
+        self.driver.connection._get_orgId()
+        DimensionDataMockHttp.type = 'ALLFILTERS'
+        self.driver.ex_list_tag_keys(id='fake_id', name='fake_name', value_required=False, display_on_report=False)
+
+    def test_ex_get_tag_by_id(self):
+        tag = self.driver.ex_get_tag_key_by_id('d047c609-93d7-4bc5-8fc9-732c85840075')
+        self.assertTrue(isinstance(tag, DimensionDataTagKey))
+
+    def test_ex_get_tag_by_id_NOEXIST(self):
+        self.driver.connection._get_orgId()
+        DimensionDataMockHttp.type = 'NOEXIST'
+        with self.assertRaises(DimensionDataAPIException):
+            self.driver.ex_get_tag_key_by_id('d047c609-93d7-4bc5-8fc9-732c85840075')
+
+    def test_ex_get_tag_by_name(self):
+        self.driver.connection._get_orgId()
+        DimensionDataMockHttp.type = 'SINGLE'
+        tag = self.driver.ex_get_tag_key_by_name('LibcloudTest')
+        self.assertTrue(isinstance(tag, DimensionDataTagKey))
+
+    def test_ex_get_tag_by_name_NOEXIST(self):
+        with self.assertRaises(ValueError):
+            self.driver.ex_get_tag_key_by_name('LibcloudTest')
+
+    def test_ex_modify_tag_key_NAME(self):
+        tag_key = self.driver.ex_list_tag_keys()[0]
+        DimensionDataMockHttp.type = 'NAME'
+        success = self.driver.ex_modify_tag_key(tag_key, name='NewName')
+        self.assertTrue(success)
+
+    def test_ex_modify_tag_key_NOTNAME(self):
+        tag_key = self.driver.ex_list_tag_keys()[0]
+        DimensionDataMockHttp.type = 'NOTNAME'
+        success = self.driver.ex_modify_tag_key(tag_key, description='NewDesc', value_required=False, display_on_report=True)
+        self.assertTrue(success)
+
+    def test_ex_modify_tag_key_NOCHANGE(self):
+        tag_key = self.driver.ex_list_tag_keys()[0]
+        DimensionDataMockHttp.type = 'NOCHANGE'
+        with self.assertRaises(DimensionDataAPIException):
+            self.driver.ex_modify_tag_key(tag_key)
+
+    def test_ex_remove_tag_key(self):
+        tag_key = self.driver.ex_list_tag_keys()[0]
+        success = self.driver.ex_remove_tag_key(tag_key)
+        self.assertTrue(success)
+
+    def test_ex_remove_tag_key_NOEXIST(self):
+        tag_key = self.driver.ex_list_tag_keys()[0]
+        DimensionDataMockHttp.type = 'NOEXIST'
+        with self.assertRaises(DimensionDataAPIException):
+            self.driver.ex_remove_tag_key(tag_key)
+
+    def test_ex_apply_tag_to_asset(self):
+        node = self.driver.list_nodes()[0]
+        success = self.driver.ex_apply_tag_to_asset(node, 'TagKeyName', 'FakeValue')
+        self.assertTrue(success)
+
+    def test_ex_apply_tag_to_asset_NOVALUE(self):
+        node = self.driver.list_nodes()[0]
+        DimensionDataMockHttp.type = 'NOVALUE'
+        success = self.driver.ex_apply_tag_to_asset(node, 'TagKeyName')
+        self.assertTrue(success)
+
+    def test_ex_apply_tag_to_asset_NOTAGKEY(self):
+        node = self.driver.list_nodes()[0]
+        DimensionDataMockHttp.type = 'NOTAGKEY'
+        with self.assertRaises(DimensionDataAPIException):
+            self.driver.ex_apply_tag_to_asset(node, 'TagKeyNam')
+
+    def test_ex_apply_tag_to_asset_BADASSETTYPE(self):
+        network = self.driver.list_networks()[0]
+        DimensionDataMockHttp.type = 'NOTAGKEY'
+        with self.assertRaises(TypeError):
+            self.driver.ex_apply_tag_to_asset(network, 'TagKeyNam')
+
+    def test_ex_remove_tag_from_asset(self):
+        node = self.driver.list_nodes()[0]
+        success = self.driver.ex_remove_tag_from_asset(node, 'TagKeyName')
+        self.assertTrue(success)
+
+    def test_ex_remove_tag_from_asset_NOTAG(self):
+        node = self.driver.list_nodes()[0]
+        DimensionDataMockHttp.type = 'NOTAG'
+        with self.assertRaises(DimensionDataAPIException):
+            self.driver.ex_remove_tag_from_asset(node, 'TagKeyNam')
+
+    def test_ex_list_tags(self):
+        tags = self.driver.ex_list_tags()
+        self.assertTrue(isinstance(tags, list))
+        self.assertTrue(isinstance(tags[0], DimensionDataTag))
+        self.assertTrue(len(tags) == 3)
+
+    def test_ex_list_tags_ALLPARAMS(self):
+        self.driver.connection._get_orgId()
+        DimensionDataMockHttp.type = 'ALLPARAMS'
+        tags = self.driver.ex_list_tags(asset_id='fake_asset_id', asset_type='fake_asset_type',
+                                        location='fake_location', tag_key_name='fake_tag_key_name',
+                                        tag_key_id='fake_tag_key_id', value='fake_value',
+                                        value_required=False, display_on_report=False)
+        self.assertTrue(isinstance(tags, list))
+        self.assertTrue(isinstance(tags[0], DimensionDataTag))
+        self.assertTrue(len(tags) == 3)
+
+    def test_priv_location_to_location_id(self):
+        location = self.driver.ex_get_location_by_id('NA9')
+        self.assertEqual(
+            self.driver._location_to_location_id(location),
+            'NA9'
+        )
+
+    def test_priv_location_to_location_id_STR(self):
+        self.assertEqual(
+            self.driver._location_to_location_id('NA9'),
+            'NA9'
+        )
+
+    def test_priv_location_to_location_id_TYPEERROR(self):
+        with self.assertRaises(TypeError):
+            self.driver._location_to_location_id([1, 2, 3])
+
+    def test_priv_image_needs_auth_os_img(self):
+        image = self.driver.list_images()[1]
+        self.assertTrue(self.driver._image_needs_auth(image))
+
+    def test_priv_image_needs_auth_os_img_STR(self):
+        image = self.driver.list_images()[1].id
+        self.assertTrue(self.driver._image_needs_auth(image))
+
+    def test_priv_image_needs_auth_cust_img_windows(self):
+        image = self.driver.ex_list_customer_images()[1]
+        self.assertTrue(self.driver._image_needs_auth(image))
+
+    def test_priv_image_needs_auth_cust_img_windows_STR(self):
+        image = self.driver.ex_list_customer_images()[1].id
+        self.assertTrue(self.driver._image_needs_auth(image))
+
+    def test_priv_image_needs_auth_cust_img_linux(self):
+        image = self.driver.ex_list_customer_images()[0]
+        self.assertTrue(not self.driver._image_needs_auth(image))
+
+    def test_priv_image_needs_auth_cust_img_linux_STR(self):
+        image = self.driver.ex_list_customer_images()[0].id
+        self.assertTrue(not self.driver._image_needs_auth(image))
+
+    def test_summary_usage_report(self):
+        report = self.driver.ex_summary_usage_report('2016-06-01', '2016-06-30')
+        report_content = report
+        self.assertEqual(len(report_content), 13)
+        self.assertEqual(len(report_content[0]), 6)
+
+    def test_detailed_usage_report(self):
+        report = self.driver.ex_detailed_usage_report('2016-06-01', '2016-06-30')
+        report_content = report
+        self.assertEqual(len(report_content), 42)
+        self.assertEqual(len(report_content[0]), 4)
+
+    def test_audit_log_report(self):
+        report = self.driver.ex_audit_log_report('2016-06-01', '2016-06-30')
+        report_content = report
+        self.assertEqual(len(report_content), 25)
+        self.assertEqual(report_content[2][2], 'OEC_SYSTEM')
+
+    def test_ex_list_ip_address_list(self):
+        net_domain = self.driver.ex_list_network_domains()[0]
+        ip_list = self.driver.ex_list_ip_address_list(
+            ex_network_domain=net_domain)
+        self.assertTrue(isinstance(ip_list, list))
+        self.assertEqual(len(ip_list), 4)
+        self.assertTrue(isinstance(ip_list[0].name, str))
+        self.assertTrue(isinstance(ip_list[0].description, str))
+        self.assertTrue(isinstance(ip_list[0].ip_version, str))
+        self.assertTrue(isinstance(ip_list[0].state, str))
+        self.assertTrue(isinstance(ip_list[0].create_time, str))
+        self.assertTrue(isinstance(ip_list[0].child_ip_address_lists, list))
+        self.assertEqual(len(ip_list[1].child_ip_address_lists), 1)
+        self.assertTrue(isinstance(ip_list[1].child_ip_address_lists[0].name,
+                                   str))
+
+    def test_ex_get_ip_address_list(self):
+        net_domain = self.driver.ex_list_network_domains()[0]
+        DimensionDataMockHttp.type = 'FILTERBYNAME'
+        ip_list = self.driver.ex_get_ip_address_list(
+            ex_network_domain=net_domain.id,
+            ex_ip_address_list_name='Test_IP_Address_List_3')
+        self.assertTrue(isinstance(ip_list, list))
+        self.assertEqual(len(ip_list), 1)
+        self.assertTrue(isinstance(ip_list[0].name, str))
+        self.assertTrue(isinstance(ip_list[0].description, str))
+        self.assertTrue(isinstance(ip_list[0].ip_version, str))
+        self.assertTrue(isinstance(ip_list[0].state, str))
+        self.assertTrue(isinstance(ip_list[0].create_time, str))
+        ips = ip_list[0].ip_address_collection
+        self.assertEqual(len(ips), 3)
+        self.assertTrue(isinstance(ips[0].begin, str))
+        self.assertTrue(isinstance(ips[0].prefix_size, str))
+        self.assertTrue(isinstance(ips[2].end, str))
+
+    def test_ex_create_ip_address_list_FAIL(self):
+        net_domain = self.driver.ex_list_network_domains()[0]
+
+        with self.assertRaises(TypeError):
+            self.driver.ex_create_ip_address_list(
+                ex_network_domain=net_domain.id)
+
+    def test_ex_create_ip_address_list(self):
+        name = "Test_IP_Address_List_3"
+        description = "Test Description"
+        ip_version = "IPV4"
+        child_ip_address_list_id = '0291ef78-4059-4bc1-b433-3f6ad698dc41'
+        child_ip_address_list = DimensionDataChildIpAddressList(
+            id=child_ip_address_list_id,
+            name="test_child_ip_addr_list")
+        net_domain = self.driver.ex_list_network_domains()[0]
+        ip_address_1 = DimensionDataIpAddress(begin='190.2.2.100')
+        ip_address_2 = DimensionDataIpAddress(begin='190.2.2.106',
+                                              end='190.2.2.108')
+        ip_address_3 = DimensionDataIpAddress(begin='190.2.2.0',
+                                              prefix_size='24')
+        ip_address_collection = [ip_address_1, ip_address_2,
+                                 ip_address_3]
+
+        # Create IP Address List
+        success = self.driver.ex_create_ip_address_list(
+            ex_network_domain=net_domain, name=name,
+            ip_version=ip_version, description=description,
+            ip_address_collection=ip_address_collection,
+            child_ip_address_list=child_ip_address_list)
+
+        self.assertTrue(success)
+
+    def test_ex_create_ip_address_list_STR(self):
+        name = "Test_IP_Address_List_3"
+        description = "Test Description"
+        ip_version = "IPV4"
+        child_ip_address_list_id = '0291ef78-4059-4bc1-b433-3f6ad698dc41'
+        net_domain = self.driver.ex_list_network_domains()[0]
+        ip_address_1 = DimensionDataIpAddress(begin='190.2.2.100')
+        ip_address_2 = DimensionDataIpAddress(begin='190.2.2.106',
+                                              end='190.2.2.108')
+        ip_address_3 = DimensionDataIpAddress(begin='190.2.2.0',
+                                              prefix_size='24')
+        ip_address_collection = [ip_address_1, ip_address_2,
+                                 ip_address_3]
+
+        # Create IP Address List
+        success = self.driver.ex_create_ip_address_list(
+            ex_network_domain=net_domain.id, name=name,
+            ip_version=ip_version, description=description,
+            ip_address_collection=ip_address_collection,
+            child_ip_address_list=child_ip_address_list_id)
+
+        self.assertTrue(success)
+
+    def test_ex_edit_ip_address_list(self):
+        ip_address_1 = DimensionDataIpAddress(begin='190.2.2.111')
+        ip_address_collection = [ip_address_1]
+
+        child_ip_address_list = DimensionDataChildIpAddressList(
+            id='2221ef78-4059-4bc1-b433-3f6ad698dc41',
+            name="test_child_ip_address_list edited")
+
+        ip_address_list = DimensionDataIpAddressList(
+            id='1111ef78-4059-4bc1-b433-3f6ad698d111',
+            name="test ip address list edited",
+            ip_version="IPv4", description="test",
+            ip_address_collection=ip_address_collection,
+            child_ip_address_lists=child_ip_address_list,
+            state="NORMAL",
+            create_time='2015-09-29T02:49:45'
+        )
+
+        success = self.driver.ex_edit_ip_address_list(
+            ex_ip_address_list=ip_address_list,
+            description="test ip address list",
+            ip_address_collection=ip_address_collection,
+            child_ip_address_lists=child_ip_address_list
+        )
+
+        self.assertTrue(success)
+
+    def test_ex_edit_ip_address_list_STR(self):
+        ip_address_1 = DimensionDataIpAddress(begin='190.2.2.111')
+        ip_address_collection = [ip_address_1]
+
+        child_ip_address_list = DimensionDataChildIpAddressList(
+            id='2221ef78-4059-4bc1-b433-3f6ad698dc41',
+            name="test_child_ip_address_list edited")
+
+        success = self.driver.ex_edit_ip_address_list(
+            ex_ip_address_list='84e34850-595d- 436e-a885-7cd37edb24a4',
+            description="test ip address list",
+            ip_address_collection=ip_address_collection,
+            child_ip_address_lists=child_ip_address_list
+        )
+
+        self.assertTrue(success)
+
+    def test_ex_delete_ip_address_list(self):
+        child_ip_address_list = DimensionDataChildIpAddressList(
+            id='2221ef78-4059-4bc1-b433-3f6ad698dc41',
+            name="test_child_ip_address_list edited")
+
+        ip_address_list = DimensionDataIpAddressList(
+            id='1111ef78-4059-4bc1-b433-3f6ad

<TRUNCATED>

[12/40] libcloud git commit: Compare version using disutils package LooseVersion

Posted by an...@apache.org.
Compare  version using disutils package LooseVersion


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

Branch: refs/heads/trunk
Commit: cd7fe0e5c8ed10f6aa8e6cf573d9239ef10bcaa4
Parents: 75111a4
Author: Samuel Chong <sa...@gmail.com>
Authored: Tue Nov 15 11:33:47 2016 +1100
Committer: Samuel Chong <sa...@gmail.com>
Committed: Tue Nov 15 11:33:47 2016 +1100

----------------------------------------------------------------------
 libcloud/common/dimensiondata.py | 13 ++++++++-----
 1 file changed, 8 insertions(+), 5 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/libcloud/blob/cd7fe0e5/libcloud/common/dimensiondata.py
----------------------------------------------------------------------
diff --git a/libcloud/common/dimensiondata.py b/libcloud/common/dimensiondata.py
index c58d5dd..3cb9f66 100644
--- a/libcloud/common/dimensiondata.py
+++ b/libcloud/common/dimensiondata.py
@@ -17,6 +17,7 @@ Dimension Data Common Components
 """
 from base64 import b64encode
 from time import sleep
+from distutils.version import LooseVersion, StrictVersion
 from libcloud.utils.py3 import httplib
 from libcloud.utils.py3 import b
 from libcloud.common.base import ConnectionUserAndKey, XmlResponse, RawResponse
@@ -375,13 +376,13 @@ class DimensionDataConnection(ConnectionUserAndKey):
     api_version_1 = 0.9
 
     # Earliest version supported
-    oldest_api_version = 2.2
+    oldest_api_version = '2.2'
 
     # Latest version supported
-    latest_api_version = 2.3
+    latest_api_version = '2.3'
 
     # Default api version
-    active_api_version = 2.3
+    active_api_version = '2.3'
 
     _orgId = None
     responseCls = DimensionDataResponse
@@ -404,7 +405,8 @@ class DimensionDataConnection(ConnectionUserAndKey):
             self.host = conn_kwargs['region']['host']
 
         if api_version:
-            if float(api_version) < self.oldest_api_version:
+            if LooseVersion(api_version) < LooseVersion(
+                    self.oldest_api_version):
                 msg = 'API Version specified is too old. No longer ' \
                       'supported. Please upgrade to the latest version {}' \
                     .format(self.active_api_version)
@@ -412,7 +414,8 @@ class DimensionDataConnection(ConnectionUserAndKey):
                 raise DimensionDataAPIException(code=None,
                                                 msg=msg,
                                                 driver=self.driver)
-            elif float(api_version) > self.latest_api_version:
+            elif LooseVersion(api_version) > LooseVersion(
+                    self.latest_api_version):
                 msg = 'Unsupported API Version. The version specified is ' \
                       'not release yet. Please use the latest supported ' \
                       'version {}' \


[34/40] libcloud git commit: Fix more pylint error

Posted by an...@apache.org.
Fix more pylint error


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

Branch: refs/heads/trunk
Commit: d1c325960d5fe2c914004687264f4fb236f57767
Parents: ba6346f
Author: Samuel Chong <sa...@gmail.com>
Authored: Fri Nov 25 11:29:50 2016 +1100
Committer: Samuel Chong <sa...@gmail.com>
Committed: Fri Nov 25 11:29:50 2016 +1100

----------------------------------------------------------------------
 libcloud/test/compute/test_dimensiondata_v2_4.py | 17 +++++++++--------
 1 file changed, 9 insertions(+), 8 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/libcloud/blob/d1c32596/libcloud/test/compute/test_dimensiondata_v2_4.py
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/test_dimensiondata_v2_4.py b/libcloud/test/compute/test_dimensiondata_v2_4.py
index ad4b980..15c29f8 100644
--- a/libcloud/test/compute/test_dimensiondata_v2_4.py
+++ b/libcloud/test/compute/test_dimensiondata_v2_4.py
@@ -2043,7 +2043,7 @@ class DimensionData_v2_4_Tests(unittest.TestCase, TestCaseMixin):
         tag_dictionaries = {'tagkey1_name': 'dev test', 'tagkey2_name': None}
 
         with self.assertRaises(ValueError):
-            success = self.driver.import_image(
+            self.driver.import_image(
                 ovf_package_name='aTestGocToNGoc2_export2.mf',
                 name='Libcloud NGOCImage_New 2',
                 description='test',
@@ -2056,7 +2056,7 @@ class DimensionData_v2_4_Tests(unittest.TestCase, TestCaseMixin):
         tag_dictionaries = {'tagkey1_name': 'dev test', 'tagkey2_name': None}
 
         with self.assertRaises(ValueError):
-            success = self.driver.import_image(
+            self.driver.import_image(
                 ovf_package_name='aTestGocToNGoc2_export2.mf',
                 name='Libcloud NGOCImage_New 2',
                 description='test',
@@ -2067,8 +2067,8 @@ class DimensionData_v2_4_Tests(unittest.TestCase, TestCaseMixin):
 
     def test_exchange_nic_vlans(self):
         success = self.driver.ex_exchange_nic_vlans(
-                  nic_id_1='a4b4b42b-ccb5-416f-b052-ce7cb7fdff12',
-                  nic_id_2='b39d09b8-ea65-424a-8fa6-c6f5a98afc69')
+                      nic_id_1='a4b4b42b-ccb5-416f-b052-ce7cb7fdff12',
+                      nic_id_2='b39d09b8-ea65-424a-8fa6-c6f5a98afc69')
         self.assertTrue(success)
 
     def test_change_nic_network_adapter(self):
@@ -2077,6 +2077,7 @@ class DimensionData_v2_4_Tests(unittest.TestCase, TestCaseMixin):
             network_adapter_name='E1000')
         self.assertTrue(success)
 
+
 class InvalidRequestError(Exception):
     def __init__(self, tag):
         super(InvalidRequestError, self).__init__("Invalid Request - %s" % tag)
@@ -3327,28 +3328,28 @@ class DimensionDataMockHttp(StorageMockHttp, MockHttp):
         return httplib.OK, body, {}, httplib.responses[httplib.OK]
 
     def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_cloneServer(
-        self, method, url, body, headers):
+            self, method, url, body, headers):
         body = self.fixtures.load(
             '2.4/server_clone_response.xml'
         )
         return httplib.OK, body, {}, httplib.responses[httplib.OK]
 
     def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_image_importImage(
-        self, method, url, body, headers):
+            self, method, url, body, headers):
         body = self.fixtures.load(
             '2.4/import_image_response.xml'
         )
         return httplib.OK, body, {}, httplib.responses[httplib.OK]
 
     def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_exchangeNicVlans(
-        self, method, url, body, headers):
+            self, method, url, body, headers):
         body = self.fixtures.load(
             '2.4/exchange_nic_vlans_response.xml'
         )
         return httplib.OK, body, {}, httplib.responses[httplib.OK]
 
     def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_changeNetworkAdapter(
-        self, method, url, body, headers):
+            self, method, url, body, headers):
         body = self.fixtures.load(
             '2.4/change_nic_networkadapter_response.xml'
         )


[24/40] libcloud git commit: Add feature to Change NIC network adapter of a server

Posted by an...@apache.org.
Add feature to Change NIC network adapter of a server


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

Branch: refs/heads/trunk
Commit: 060954eb30dc376f5eec0b49be7a480e25e70c64
Parents: 8404532
Author: Samuel Chong <sa...@gmail.com>
Authored: Thu Nov 17 15:10:08 2016 +1100
Committer: Samuel Chong <sa...@gmail.com>
Committed: Thu Nov 17 15:10:08 2016 +1100

----------------------------------------------------------------------
 libcloud/compute/drivers/dimensiondata.py       | 31 ++++++++++++++++++++
 .../2.4/change_nic_networkadapter_response.xml  |  7 +++++
 .../test/compute/test_dimensiondata_v2_4.py     | 13 ++++++++
 3 files changed, 51 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/libcloud/blob/060954eb/libcloud/compute/drivers/dimensiondata.py
----------------------------------------------------------------------
diff --git a/libcloud/compute/drivers/dimensiondata.py b/libcloud/compute/drivers/dimensiondata.py
index 6f0a197..eec32a6 100644
--- a/libcloud/compute/drivers/dimensiondata.py
+++ b/libcloud/compute/drivers/dimensiondata.py
@@ -3720,6 +3720,37 @@ class DimensionDataNodeDriver(NodeDriver):
         response_code = findtext(response, 'responseCode', TYPES_URN)
         return response_code in ['IN_PROGRESS', 'OK']
 
+    def ex_change_nic_network_adapter(self, nic_id, network_adapter_name):
+        """
+        Change network adapter of a NIC on a cloud server
+
+        :param    nic_id:  Nic ID
+        :type     nic_id: :``str``
+
+        :param    network_adapter_name:  Network adapter name
+        :type     network_adapter_name: :``str``
+
+        :rtype: ``bool``
+        """
+
+        change_elem = ET.Element(
+            'changeNetworkAdapter',
+            {
+                'nicId': nic_id,
+                'xmlns': TYPES_URN
+            })
+
+        ET.SubElement(change_elem, 'networkAdapter').text = \
+            network_adapter_name
+
+        response = self.connection.request_with_orgId_api_2(
+            'server/changeNetworkAdapter',
+            method='POST',
+            data=ET.tostring(change_elem)).object
+
+        response_code = findtext(response, 'responseCode', TYPES_URN)
+        return response_code in ['IN_PROGRESS', 'OK']
+
     def _format_csv(self, http_response):
         text = http_response.read()
         lines = str.splitlines(ensure_string(text))

http://git-wip-us.apache.org/repos/asf/libcloud/blob/060954eb/libcloud/test/compute/fixtures/dimensiondata/2.4/change_nic_networkadapter_response.xml
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/dimensiondata/2.4/change_nic_networkadapter_response.xml b/libcloud/test/compute/fixtures/dimensiondata/2.4/change_nic_networkadapter_response.xml
new file mode 100644
index 0000000..40b60a5
--- /dev/null
+++ b/libcloud/test/compute/fixtures/dimensiondata/2.4/change_nic_networkadapter_response.xml
@@ -0,0 +1,7 @@
+<response requestId="na/2014-04-14T13:37:20/62f06368-c3fb-11e3-b29c-001517c4643e"
+xmlns="urn:didata.com:api:cloud:types">
+  <operation>CHANGE_NETWORK_ADAPTER</operation>
+  <responseCode>IN_PROGRESS</responseCode>
+  <message>Request to Change Network Adapter for NIC with Id 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/060954eb/libcloud/test/compute/test_dimensiondata_v2_4.py
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/test_dimensiondata_v2_4.py b/libcloud/test/compute/test_dimensiondata_v2_4.py
index d835b5c..caef5a8 100644
--- a/libcloud/test/compute/test_dimensiondata_v2_4.py
+++ b/libcloud/test/compute/test_dimensiondata_v2_4.py
@@ -2045,6 +2045,12 @@ class DimensionData_v2_4_Tests(unittest.TestCase, TestCaseMixin):
                   nic_id_2='b39d09b8-ea65-424a-8fa6-c6f5a98afc69')
         self.assertTrue(success)
 
+    def test_change_nic_network_adapter(self):
+        success = self.driver.ex_change_nic_network_adapter(
+            nic_id='0c55c269-20a5-4fec-8054-22a245a48fe4',
+            network_adapter_name='E1000')
+        self.assertTrue(success)
+
 class InvalidRequestError(Exception):
     def __init__(self, tag):
         super(InvalidRequestError, self).__init__("Invalid Request - %s" % tag)
@@ -3315,5 +3321,12 @@ class DimensionDataMockHttp(StorageMockHttp, MockHttp):
         )
         return httplib.OK, body, {}, httplib.responses[httplib.OK]
 
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_changeNetworkAdapter(
+        self, method, url, body, headers):
+        body = self.fixtures.load(
+            '2.4/change_nic_networkadapter_response.xml'
+        )
+        return httplib.OK, body, {}, httplib.responses[httplib.OK]
+
 if __name__ == '__main__':
     sys.exit(unittest.main())


[40/40] libcloud git commit: change for #953

Posted by an...@apache.org.
change for #953


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

Branch: refs/heads/trunk
Commit: 75b129e8b2d861e3853738ac9a0ff18362108404
Parents: a77e418
Author: Anthony Shaw <an...@apache.org>
Authored: Fri Dec 2 15:32:43 2016 +1100
Committer: Anthony Shaw <an...@apache.org>
Committed: Fri Dec 2 15:32:43 2016 +1100

----------------------------------------------------------------------
 CHANGES.rst | 5 +++++
 1 file changed, 5 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/libcloud/blob/75b129e8/CHANGES.rst
----------------------------------------------------------------------
diff --git a/CHANGES.rst b/CHANGES.rst
index c59861f..4932d8d 100644
--- a/CHANGES.rst
+++ b/CHANGES.rst
@@ -8,6 +8,11 @@ Changes in current version of Apache Libcloud
 Compute
 ~~~~~~~
 
+- [dimensiondata] Added support for 2.4 API, added support for image import, cloning. Add feature for changing NIC VLANs, add feature for changing
+  NIC order for a server.
+  (GITHUB-953)
+  [Samuel Chong]
+
 - [ec2] Add US-EAST2 (Ohio)
   (GITHUB-946)
   [Matthew Harris]


[37/40] libcloud git commit: Fix merge conflict

Posted by an...@apache.org.
Fix merge conflict


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

Branch: refs/heads/trunk
Commit: 739a8204d646c677b6cd2e4949588fee1b2d5f82
Parents: 8db131a 216a24f
Author: Samuel Chong <sa...@gmail.com>
Authored: Thu Dec 1 09:16:58 2016 +1100
Committer: Samuel Chong <sa...@gmail.com>
Committed: Thu Dec 1 09:16:58 2016 +1100

----------------------------------------------------------------------
 CHANGES.rst                     |  4 ++++
 doap_libcloud.rdf               |  7 +++++++
 libcloud/compute/drivers/gce.py | 32 +++++++++++++++++++-------------
 libcloud/test/secrets.py-dist   |  2 +-
 4 files changed, 31 insertions(+), 14 deletions(-)
----------------------------------------------------------------------



[21/40] libcloud git commit: Unit tests for caas api version 2.4

Posted by an...@apache.org.
Unit tests for caas api version 2.4


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

Branch: refs/heads/trunk
Commit: 1bafa61da2980b5425ec34f11de5cd5d8c6ec446
Parents: 3ab1a46
Author: Samuel Chong <sa...@gmail.com>
Authored: Wed Nov 16 10:02:31 2016 +1100
Committer: Samuel Chong <sa...@gmail.com>
Committed: Wed Nov 16 10:02:31 2016 +1100

----------------------------------------------------------------------
 libcloud/compute/drivers/dimensiondata.py       |   3 +-
 libcloud/test/backup/test_dimensiondata_v2_3.py |   2 +-
 libcloud/test/backup/test_dimensiondata_v2_4.py |   2 +-
 .../dimensiondata/2.4/image_customerImage.xml   |  19 +-
 ...age_2ffa36c8_1848_49eb_b4fa_9d908775f68c.xml |   6 +-
 ...age_5234e5c7_01de_4411_8b6e_baeb8d91cf5d.xml |   6 +-
 .../dimensiondata/2.4/image_osImage.xml         |  12 +-
 ...age_6b4fb0c7_a57b_4f58_b59c_9958f94f971a.xml |   4 +-
 ...age_c14b1a46_2428_44c1_9c1a_b20e6418d08c.xml |   4 +-
 .../dimensiondata/2.4/server_GetServer.xml      |  42 ++++
 .../dimensiondata/2.4/server_cleanServer.xml    |   9 +
 .../dimensiondata/2.4/server_clone_response.xml |   9 +
 .../dimensiondata/2.4/server_server.xml         | 192 +++++++++++++++++++
 .../dimensiondata/2.4/server_server_NA3.xml     |  56 ++++++
 ...ver_e75ead52_692f_4314_8725_c8a4f4d13a87.xml |  30 +++
 .../2.4/server_server_paginated.xml             |  58 ++++++
 .../test/compute/test_dimensiondata_v2_3.py     |   2 +-
 .../test/compute/test_dimensiondata_v2_4.py     |  39 ++--
 .../loadbalancer/test_dimensiondata_v2_3.py     |   2 +-
 .../loadbalancer/test_dimensiondata_v2_4.py     |   2 +-
 20 files changed, 462 insertions(+), 37 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/libcloud/blob/1bafa61d/libcloud/compute/drivers/dimensiondata.py
----------------------------------------------------------------------
diff --git a/libcloud/compute/drivers/dimensiondata.py b/libcloud/compute/drivers/dimensiondata.py
index ab3a0a7..60056b4 100644
--- a/libcloud/compute/drivers/dimensiondata.py
+++ b/libcloud/compute/drivers/dimensiondata.py
@@ -3703,8 +3703,9 @@ class DimensionDataNodeDriver(NodeDriver):
         raise TypeError("Asset type %s cannot be tagged" % objecttype.__name__)
 
     def _list_nodes_single_page(self, params={}):
-        return self.connection.request_with_orgId_api_2(
+        nodes = self.connection.request_with_orgId_api_2(
             'server/server', params=params).object
+        return nodes
 
     def _to_tags(self, object):
         tags = []

http://git-wip-us.apache.org/repos/asf/libcloud/blob/1bafa61d/libcloud/test/backup/test_dimensiondata_v2_3.py
----------------------------------------------------------------------
diff --git a/libcloud/test/backup/test_dimensiondata_v2_3.py b/libcloud/test/backup/test_dimensiondata_v2_3.py
index ae05316..b0e581a 100644
--- a/libcloud/test/backup/test_dimensiondata_v2_3.py
+++ b/libcloud/test/backup/test_dimensiondata_v2_3.py
@@ -34,7 +34,7 @@ from libcloud.test.file_fixtures import BackupFileFixtures
 from libcloud.test.secrets import DIMENSIONDATA_PARAMS
 
 
-class DimensionDataTests(unittest.TestCase, TestCaseMixin):
+class DimensionData_v2_3_Tests(unittest.TestCase, TestCaseMixin):
 
     def setUp(self):
         DimensionData.connectionCls.active_api_version = '2.3'

http://git-wip-us.apache.org/repos/asf/libcloud/blob/1bafa61d/libcloud/test/backup/test_dimensiondata_v2_4.py
----------------------------------------------------------------------
diff --git a/libcloud/test/backup/test_dimensiondata_v2_4.py b/libcloud/test/backup/test_dimensiondata_v2_4.py
index d5da857..285ac40 100644
--- a/libcloud/test/backup/test_dimensiondata_v2_4.py
+++ b/libcloud/test/backup/test_dimensiondata_v2_4.py
@@ -34,7 +34,7 @@ from libcloud.test.file_fixtures import BackupFileFixtures
 from libcloud.test.secrets import DIMENSIONDATA_PARAMS
 
 
-class DimensionDataTests(unittest.TestCase, TestCaseMixin):
+class DimensionData_v2_4_Tests(unittest.TestCase, TestCaseMixin):
 
     def setUp(self):
         DimensionData.connectionCls.active_api_version = '2.4'

http://git-wip-us.apache.org/repos/asf/libcloud/blob/1bafa61d/libcloud/test/compute/fixtures/dimensiondata/2.4/image_customerImage.xml
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/dimensiondata/2.4/image_customerImage.xml b/libcloud/test/compute/fixtures/dimensiondata/2.4/image_customerImage.xml
index 4e59e18..16e679e 100644
--- a/libcloud/test/compute/fixtures/dimensiondata/2.4/image_customerImage.xml
+++ b/libcloud/test/compute/fixtures/dimensiondata/2.4/image_customerImage.xml
@@ -3,7 +3,10 @@
     <customerImage id="5234e5c7-01de-4411-8b6e-baeb8d91cf5d" datacenterId="NA9">
         <name>ImportedCustomerImage</name>
         <description />
-        <operatingSystem id="REDHAT664" displayName="REDHAT6/64" family="UNIX" />
+        <guest osCustomization="true">
+            <operatingSystem id="REDHAT664" displayName="REDHAT6/64" family="UNIX" />
+            <vmTools versionStatus="CURRENT" runningStatus="NOT_RUNNING" />
+        </guest>
         <cpu count="4" speed="STANDARD" coresPerSocket="1" />
         <memoryGb>2</memoryGb>
         <disk id="1a82316f-23ed-4fe9-b6d8-6b92ac467423" scsiId="0" sizeGb="12" speed="STANDARD" />
@@ -13,13 +16,16 @@
         <artifact type="OVF" value="ImportedCustomerImage.ovf" date="2015-1119T14:28:05.000Z" />
         <artifact type="VMDK" value="ImportedCustomerImage-disk1.vmdk" date="2015-11-19T12:22:31.000Z" /></source>
         <state>NORMAL</state>
-        <vmwareTools versionStatus="NEED_UPGRADE" runningStatus="NOT_RUNNING" apiVersion="8389" />
+        <vmTools versionStatus="NEED_UPGRADE" runningStatus="NOT_RUNNING" apiVersion="8389" />
         <virtualHardware version="vmx-10" upToDate="true" />
     </customerImage>
     <customerImage id="2ffa36c8-1848-49eb-b4fa-9d908775f68c" datacenterId="NA9">
         <name>CustomerImageWithPricedSoftwareLabels</name>
         <description />
-        <operatingSystem id="WIN2008S32" displayName="WIN2008S/32" family="WINDOWS" />
+        <guest osCustomization="true">
+            <operatingSystem id="WIN2008S32" displayName="WIN2008S/32" family="WINDOWS" />
+            <vmTools versionStatus="CURRENT" runningStatus="NOT_RUNNING" />
+        </guest>
         <cpu count="1" speed="STANDARD" coresPerSocket="1" />
         <memoryGb>1</memoryGb>
         <disk id="29455efc-51af-4b4d-91b3-d81ca0dff7d8" scsiId="0" sizeGb="50" speed="STANDARD" />
@@ -29,13 +35,15 @@
             <artifact type="SERVER_ID" value="7c9c2551-269d-4274-a247126ba7c6215c" />
         </source>
         <state>NORMAL</state>
-        <vmwareTools versionStatus="CURRENT" runningStatus="NOT_RUNNING" />
         <virtualHardware version="vmx-08" upToDate="false" />
     </customerImage>
     <customerImage id="1fc1844f-45d6-4364-b447-f7c7645b47de" datacenterId="NA9">
         <name>CopiedCustomerImage</name>
         <description />
-        <operatingSystem id="REDHAT664" displayName="REDHAT6/64" family="UNIX" />
+        <guest osCustomization="true">
+            <operatingSystem id="REDHAT664" displayName="REDHAT6/64" family="UNIX" />
+            <vmTools versionStatus="NEED_UPGRADE" runningStatus="NOT_RUNNING" apiVersion="9355" />
+        </guest>
         <cpu count="1" speed="STANDARD" coresPerSocket="1" />
         <memoryGb>2</memoryGb>
         <disk id="42b20819-c161-4dec-aa94-73ec370a6e37" scsiId="0" sizeGb="10" speed="STANDARD" />
@@ -44,7 +52,6 @@
             <artifact type="IMAGE_ID" value="0b8357b6-f156-4b27-b4fd-b81d09c15efc" />
         </source>
         <state>NORMAL</state>
-        <vmwareTools versionStatus="NEED_UPGRADE" runningStatus="NOT_RUNNING" apiVersion="9355" />
         <virtualHardware version="vmx-10" upToDate="true" />
     </customerImage>
 </customerImages>

http://git-wip-us.apache.org/repos/asf/libcloud/blob/1bafa61d/libcloud/test/compute/fixtures/dimensiondata/2.4/image_customerImage_2ffa36c8_1848_49eb_b4fa_9d908775f68c.xml
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/dimensiondata/2.4/image_customerImage_2ffa36c8_1848_49eb_b4fa_9d908775f68c.xml b/libcloud/test/compute/fixtures/dimensiondata/2.4/image_customerImage_2ffa36c8_1848_49eb_b4fa_9d908775f68c.xml
index bff6183..9ca90f8 100644
--- a/libcloud/test/compute/fixtures/dimensiondata/2.4/image_customerImage_2ffa36c8_1848_49eb_b4fa_9d908775f68c.xml
+++ b/libcloud/test/compute/fixtures/dimensiondata/2.4/image_customerImage_2ffa36c8_1848_49eb_b4fa_9d908775f68c.xml
@@ -2,7 +2,10 @@
     <customerImage xmlns="urn:didata.com:api:cloud:types" id="2ffa36c8-1848-49eb-b4fa-9d908775f68c" datacenterId="NA9">
         <name>CustomerImageWithPricedSoftwareLabels</name>
         <description />
-        <operatingSystem id="WIN2008S32" displayName="WIN2008S/32" family="WINDOWS" />
+        <guest osCustomization="true">
+            <operatingSystem id="WIN2008S32" displayName="WIN2008S/32" family="WINDOWS" />
+            <vmTools versionStatus="CURRENT" runningStatus="NOT_RUNNING" />
+        </guest>
         <cpu count="1" speed="STANDARD" coresPerSocket="1" />
         <memoryGb>1</memoryGb>
         <disk id="29455efc-51af-4b4d-91b3-d81ca0dff7d8" scsiId="0" sizeGb="50" speed="STANDARD" />
@@ -12,6 +15,5 @@
             <artifact type="SERVER_ID" value="7c9c2551-269d-4274-a247126ba7c6215c" />
         </source>
         <state>NORMAL</state>
-        <vmwareTools versionStatus="CURRENT" runningStatus="NOT_RUNNING" />
         <virtualHardware version="vmx-08" upToDate="false" />
     </customerImage>

http://git-wip-us.apache.org/repos/asf/libcloud/blob/1bafa61d/libcloud/test/compute/fixtures/dimensiondata/2.4/image_customerImage_5234e5c7_01de_4411_8b6e_baeb8d91cf5d.xml
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/dimensiondata/2.4/image_customerImage_5234e5c7_01de_4411_8b6e_baeb8d91cf5d.xml b/libcloud/test/compute/fixtures/dimensiondata/2.4/image_customerImage_5234e5c7_01de_4411_8b6e_baeb8d91cf5d.xml
index db5302d..e604436 100644
--- a/libcloud/test/compute/fixtures/dimensiondata/2.4/image_customerImage_5234e5c7_01de_4411_8b6e_baeb8d91cf5d.xml
+++ b/libcloud/test/compute/fixtures/dimensiondata/2.4/image_customerImage_5234e5c7_01de_4411_8b6e_baeb8d91cf5d.xml
@@ -2,7 +2,10 @@
     <customerImage xmlns="urn:didata.com:api:cloud:types" id="5234e5c7-01de-4411-8b6e-baeb8d91cf5d" datacenterId="NA9">
         <name>ImportedCustomerImage</name>
         <description />
-        <operatingSystem id="REDHAT664" displayName="REDHAT6/64" family="UNIX" />
+        <guest osCustomization="true">
+              <operatingSystem id="REDHAT664" displayName="REDHAT6/64" family="UNIX" />
+              <vmTools versionStatus="NEED_UPGRADE" runningStatus="NOT_RUNNING" apiVersion="8389" />
+        </guest>
         <cpu count="4" speed="STANDARD" coresPerSocket="1" />
         <memoryGb>2</memoryGb>
         <disk id="1a82316f-23ed-4fe9-b6d8-6b92ac467423" scsiId="0" sizeGb="12" speed="STANDARD" />
@@ -12,6 +15,5 @@
         <artifact type="OVF" value="ImportedCustomerImage.ovf" date="2015-1119T14:28:05.000Z" />
         <artifact type="VMDK" value="ImportedCustomerImage-disk1.vmdk" date="2015-11-19T12:22:31.000Z" /></source>
         <state>NORMAL</state>
-        <vmwareTools versionStatus="NEED_UPGRADE" runningStatus="NOT_RUNNING" apiVersion="8389" />
         <virtualHardware version="vmx-10" upToDate="true" />
     </customerImage>

http://git-wip-us.apache.org/repos/asf/libcloud/blob/1bafa61d/libcloud/test/compute/fixtures/dimensiondata/2.4/image_osImage.xml
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/dimensiondata/2.4/image_osImage.xml b/libcloud/test/compute/fixtures/dimensiondata/2.4/image_osImage.xml
index 1f884a9..b31b42f 100644
--- a/libcloud/test/compute/fixtures/dimensiondata/2.4/image_osImage.xml
+++ b/libcloud/test/compute/fixtures/dimensiondata/2.4/image_osImage.xml
@@ -3,32 +3,38 @@
     <osImage id="c14b1a46-2428-44c1-9c1a-b20e6418d08c" datacenterId="NA9">
         <name>RedHat 6 64-bit 2 CPU</name>
         <description>RedHat 6.6 Enterprise (Santiago) 64-bit</description>
-        <operatingSystem id="REDHAT664" displayName="REDHAT6/64" family="UNIX" />
         <cpu count="2" speed="STANDARD" coresPerSocket="1" />
         <memoryGb>4</memoryGb>
         <disk id="a02b7244-99d8-4889-84a5-5e4373c1bb26" scsiId="0" sizeGb="10" speed="STANDARD" />
         <createTime>2015-09-17T11:23:48.000Z</createTime>
         <osImageKey>T-RHEL-6-64-2-4-10</osImageKey>
+        <guest osCustomization="true">
+            <operatingSystem id="REDHAT664" displayName="REDHAT6/64" family="UNIX" />
+        </guest>
     </osImage>
     <osImage id="6b4fb0c7-a57b-4f58-b59c-9958f94f971a" datacenterId="NA9">
         <name>Win2012 DC 2 CPU</name>
         <description>Windows 2012 Datacenter</description>
-        <operatingSystem id="WIN2012DC64" displayName="WIN2012DC/64" family="WINDOWS" />
         <cpu count="2" speed="STANDARD" coresPerSocket="1" />
         <memoryGb>4</memoryGb>
         <disk id="f5e01854-a211-4ec6-96d6-2753b6d47877" scsiId="0" sizeGb="50" speed="STANDARD" />
         <createTime>2015-09-17T11:44:43.000Z</createTime>
         <osImageKey>T-WIN-2012-DATACTR-64-2-4-50</osImageKey>
+        <guest osCustomization="true">
+             <operatingSystem id="WIN2012DC64" displayName="WIN2012DC/64" family="WINDOWS" />
+        </guest>
     </osImage>
     <osImage id="3ebf3c0f-90fe-4a8b-8585-6e65b316592c" datacenterId="NA9">
         <name>Win2008 Std 32-bit 2 CPU</name>
         <description>Windows 2008 Enterprise R2 32-bit installed with Microsoft SQL Server 2012 Standard Edition</description>
-        <operatingSystem id="WIN2008S32" displayName="WIN2008S/32" family="WINDOWS" />
         <cpu count="2" speed="STANDARD" coresPerSocket="1" />
         <memoryGb>4</memoryGb>
         <disk id="6e5b5112-0eae-44eb-83cd-1bd0d58fbeab" scsiId="0" sizeGb="50" speed="STANDARD" />
         <softwareLabel>MSSQL2008R2S</softwareLabel>
         <createTime>2014-11-20T12:54:22.000Z</createTime>
         <osImageKey>T-WIN-2008-ENT-32-2-4-50</osImageKey>
+        <guest osCustomization="true">
+             <operatingSystem id="WIN2008S32" displayName="WIN2008S/32" family="WINDOWS" />
+        </guest>
     </osImage>
 </osImages>

http://git-wip-us.apache.org/repos/asf/libcloud/blob/1bafa61d/libcloud/test/compute/fixtures/dimensiondata/2.4/image_osImage_6b4fb0c7_a57b_4f58_b59c_9958f94f971a.xml
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/dimensiondata/2.4/image_osImage_6b4fb0c7_a57b_4f58_b59c_9958f94f971a.xml b/libcloud/test/compute/fixtures/dimensiondata/2.4/image_osImage_6b4fb0c7_a57b_4f58_b59c_9958f94f971a.xml
index 1631137..75e2f93 100644
--- a/libcloud/test/compute/fixtures/dimensiondata/2.4/image_osImage_6b4fb0c7_a57b_4f58_b59c_9958f94f971a.xml
+++ b/libcloud/test/compute/fixtures/dimensiondata/2.4/image_osImage_6b4fb0c7_a57b_4f58_b59c_9958f94f971a.xml
@@ -2,10 +2,12 @@
   <osImage xmlns="urn:didata.com:api:cloud:types" id="6b4fb0c7-a57b-4f58-b59c-9958f94f971a" datacenterId="NA9">
     <name>Win2012 DC 2 CPU</name>
     <description>Windows 2012 Datacenter</description>
-    <operatingSystem id="WIN2012DC64" displayName="WIN2012DC/64" family="WINDOWS" />
     <cpu count="2" speed="STANDARD" coresPerSocket="1" />
     <memoryGb>4</memoryGb>
     <disk id="f5e01854-a211-4ec6-96d6-2753b6d47877" scsiId="0" sizeGb="50" speed="STANDARD" />
     <createTime>2015-09-17T11:44:43.000Z</createTime>
     <osImageKey>T-WIN-2012-DATACTR-64-2-4-50</osImageKey>
+    <guest osCustomization="true">
+        <operatingSystem id="WIN2012DC64" displayName="WIN2012DC/64" family="WINDOWS" />
+    </guest>
   </osImage>

http://git-wip-us.apache.org/repos/asf/libcloud/blob/1bafa61d/libcloud/test/compute/fixtures/dimensiondata/2.4/image_osImage_c14b1a46_2428_44c1_9c1a_b20e6418d08c.xml
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/dimensiondata/2.4/image_osImage_c14b1a46_2428_44c1_9c1a_b20e6418d08c.xml b/libcloud/test/compute/fixtures/dimensiondata/2.4/image_osImage_c14b1a46_2428_44c1_9c1a_b20e6418d08c.xml
index 27d6c25..87d47f5 100644
--- a/libcloud/test/compute/fixtures/dimensiondata/2.4/image_osImage_c14b1a46_2428_44c1_9c1a_b20e6418d08c.xml
+++ b/libcloud/test/compute/fixtures/dimensiondata/2.4/image_osImage_c14b1a46_2428_44c1_9c1a_b20e6418d08c.xml
@@ -2,11 +2,13 @@
   <osImage xmlns="urn:didata.com:api:cloud:types" id="c14b1a46-2428-44c1-9c1a-b20e6418d08c" datacenterId="NA9">
     <name>RedHat 6 64-bit 2 CPU</name>
     <description>RedHat 6.6 Enterprise (Santiago) 64-bit</description>
-    <operatingSystem id="REDHAT664" displayName="REDHAT6/64" family="UNIX" />
     <cpu count="2" speed="STANDARD" coresPerSocket="1" />
     <memoryGb>4</memoryGb>
     <disk id="a02b7244-99d8-4889-84a5-5e4373c1bb26" scsiId="0" sizeGb="10" speed="STANDARD" />
     <createTime>2015-09-17T11:23:48.000Z</createTime>
     <osImageKey>T-RHEL-6-64-2-4-10</osImageKey>
+    <guest osCustomization="true">
+        <operatingSystem id="REDHAT664" displayName="REDHAT6/64" family="UNIX" />
+    </guest>
   </osImage>
 

http://git-wip-us.apache.org/repos/asf/libcloud/blob/1bafa61d/libcloud/test/compute/fixtures/dimensiondata/2.4/server_GetServer.xml
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/dimensiondata/2.4/server_GetServer.xml b/libcloud/test/compute/fixtures/dimensiondata/2.4/server_GetServer.xml
new file mode 100644
index 0000000..1103422
--- /dev/null
+++ b/libcloud/test/compute/fixtures/dimensiondata/2.4/server_GetServer.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<server id="5a32d6e4-9707-4813-a269-56ab4d989f4d" datacenterId="NA9">
+    <name>Production Web Server</name>
+    <description>Server to host our main web application.</description>
+
+    <cpu count="2" speed="STANDARD" coresPerSocket="1"/>
+    <memoryGb>4</memoryGb>
+    <disk id="c2e1f199-116e-4dbc-9960-68720b832b0a" scsiId="0" sizeGb="50"
+          speed="STANDARD" state="NORMAL"/>
+    <networkInfo networkDomainId="553f26b6-2a73-42c3-a78b-6116f11291d0">
+        <primaryNic id="5e869800-df7b-4626-bcbf-8643b8be11fd"
+                    privateIpv4="10.0.4.8"
+                    ipv6="2607:f480:1111:1282:2960:fb72:7154:6160"
+                    vlanId="bc529e20-dc6f-42ba-be20-0ffe44d1993f"
+                    vlanName="Production VLAN" state="NORMAL"/>
+    </networkInfo>
+    <backup assetId="5579f3a7-4c32-4cf5-8a7e-b45c36a35c10"
+            servicePlan="Enterprise" state="NORMAL"/>
+    <monitoring monitoringId="11049" servicePlan="ESSENTIALS" state="NORMAL"/>
+    <softwareLabel>MSSQL2008R2S</softwareLabel>
+    <sourceImageId>3ebf3c0f-90fe-4a8b-8585-6e65b316592c</sourceImageId>
+    <createTime>2015-12-02T10:31:33.000Z</createTime>
+    <deployed>true</deployed>
+    <started>true</started>
+    <state>stopped</state>
+    <progress>
+        <action>SHUTDOWN_SERVER</action>
+        <requestTime>2015-12-02T11:07:40.000Z</requestTime>
+        <userName>devuser1</userName>
+    </progress>
+    <guest osCustomization="true">
+        <operatingSystem id="WIN2008S32" displayName="WIN2008S/32"
+                     family="WINDOWS"/>
+        <vmTools versionStatus="CURRENT" runningStatus="RUNNING"
+                 apiVersion="9354"/>
+    </guest>
+    <virtualHardware version="vmx-08"
+                     upToDate="false"/> <!-- DRS: drsEligible or consistencyGroup or neither -->
+    <drsEligible/>
+    **OR**
+    <consistencyGroup id="1f4ef-1238933-2344adce-1098" name="ProductionCG" status="DRS_MODE" serverRole="TARGET"/>
+</server>

http://git-wip-us.apache.org/repos/asf/libcloud/blob/1bafa61d/libcloud/test/compute/fixtures/dimensiondata/2.4/server_cleanServer.xml
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/dimensiondata/2.4/server_cleanServer.xml b/libcloud/test/compute/fixtures/dimensiondata/2.4/server_cleanServer.xml
new file mode 100644
index 0000000..011dfd4
--- /dev/null
+++ b/libcloud/test/compute/fixtures/dimensiondata/2.4/server_cleanServer.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<response
+xmlns="urn:didata.com:api:cloud:types" requestId="au/2016-04-
+14T10:08:07.701+10:00/1cc24d5e-4612-499b-a5d4-8fd5dbb511f0">
+<operation>CLEAN_SERVER</operation>
+<responseCode>IN_PROGRESS</responseCode>
+<message>The request to clean a failed Server deployment for Server
+e75ead52-692f-4314-8725-c8a4f4d13a87 has been accepted and is being processed.</message>
+</response>

http://git-wip-us.apache.org/repos/asf/libcloud/blob/1bafa61d/libcloud/test/compute/fixtures/dimensiondata/2.4/server_clone_response.xml
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/dimensiondata/2.4/server_clone_response.xml b/libcloud/test/compute/fixtures/dimensiondata/2.4/server_clone_response.xml
new file mode 100644
index 0000000..8f7c191
--- /dev/null
+++ b/libcloud/test/compute/fixtures/dimensiondata/2.4/server_clone_response.xml
@@ -0,0 +1,9 @@
+ <response requestId= "na/2014-04-14T13:37:20/62f06368-c3fb-11e3-b29c-001517c4643e"
+xmlns= "urn:didata.com:api:cloud:types" >
+   <operation>CLONE_SERVER</operation>
+   <responseCode>IN_PROGRESS</responseCode>
+   <message>Request to Clone Server '9ed47330-5561-11e5-8c14-b8ca3a5d9ef8' has been
+accepted and is being processed.</message>
+   <info name="imageId" value="3389ffe8-c3fc-11e3-b29c-001517c4643e"/>
+   <info name="clusterId" value="33dsadsae8-c3fc-11e3-b29c-001517c4643e"/>
+</response>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/libcloud/blob/1bafa61d/libcloud/test/compute/fixtures/dimensiondata/2.4/server_server.xml
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/dimensiondata/2.4/server_server.xml b/libcloud/test/compute/fixtures/dimensiondata/2.4/server_server.xml
new file mode 100644
index 0000000..be9760a
--- /dev/null
+++ b/libcloud/test/compute/fixtures/dimensiondata/2.4/server_server.xml
@@ -0,0 +1,192 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<servers xmlns="urn:didata.com:api:cloud:types" pageNumber="1" pageCount="2" totalCount="2" pageSize="250">
+    <!-- MCP 1.0 Server State: RUNNING-->
+    <server id="e75ead52-692f-4314-8725-c8a4f4d13a87" datacenterId="NA1">
+        <name>Production Web Server MCP 1</name>
+        <description>nopassword0</description>
+        <guest osCustomization="true">
+            <operatingSystem id="REDHAT632" displayName="REDHAT6/32" family="UNIX" />
+            <vmTools versionStatus="NEED_UPGRADE" runningStatus="RUNNING" apiVersion="8389" />
+        </guest>
+        <cpu count="4" speed="STANDARD" coresPerSocket="1" />
+        <memoryGb>2</memoryGb>
+        <disk id="74f81c56-96cc-4cca-b4d7-a88f641a6ea2" scsiId="0" sizeGb="10" speed="STANDARD" state="NORMAL" />
+        <nic id="43b24e9e-c1c9-4d53-965b-89bcaa725103" privateIpv4="10.160.117.25" networkId="c550be0e-65c1-11e4-811f-005056806999" networkName="Test1" state="NORMAL" />
+        <backup assetId="5579f3a7-4c32-4cf5-8a7e-b45c36a35c10" servicePlan="Enterprise" state="NORMAL" />
+        <monitoring monitoringId="11049" servicePlan="ESSENTIALS" state="NORMAL" />
+        <sourceImageId>e9ec6eb4-4634-49de-b914-01eb74da5fb9</sourceImageId>
+        <createTime>2015-08-11T16:51:05.000Z</createTime>
+        <deployed>true</deployed>
+        <started>true</started>
+        <state>NORMAL</state>
+        <virtualHardware version="vmx-08" upToDate="false" />
+    </server>
+    <!-- MCP 1.0 Server State: STARTING-->
+    <server id="e75ead52-692f-4314-8725-c8a4f4d13a88" datacenterId="NA1">
+        <name>Production Web Server MCP 1</name>
+        <description>nopassword0</description>
+        <guest osCustomization="true">
+            <operatingSystem id="REDHAT632" displayName="REDHAT6/32" family="UNIX" />
+            <vmTools versionStatus="NEED_UPGRADE" runningStatus="RUNNING" apiVersion="8389" />
+        </guest>
+        <cpu count="4" speed="STANDARD" coresPerSocket="1" />
+        <memoryGb>2</memoryGb>
+        <disk id="74f81c56-96cc-4cca-b4d7-a88f641a6ea2" scsiId="0" sizeGb="10" speed="STANDARD" state="NORMAL" />
+        <nic id="43b24e9e-c1c9-4d53-965b-89bcaa725103" privateIpv4="10.160.117.25" networkId="c550be0e-65c1-11e4-811f-005056806999" networkName="Test1" state="NORMAL" />
+        <backup assetId="5579f3a7-4c32-4cf5-8a7e-b45c36a35c10" servicePlan="Enterprise" state="NORMAL" />
+        <monitoring monitoringId="11049" servicePlan="ESSENTIALS" state="NORMAL" />
+        <sourceImageId>e9ec6eb4-4634-49de-b914-01eb74da5fb9</sourceImageId>
+        <createTime>2015-08-11T16:51:05.000Z</createTime>
+        <deployed>true</deployed>
+        <started>true</started>
+        <state>PENDING_ADD</state>
+        <progress>
+            <action>DEPLOY_SERVER_WITH_DISK_SPEED</action>
+            <requestTime>2015-12-02T11:07:40.000Z</requestTime>
+            <userName>devuser1</userName>
+        </progress>
+        <virtualHardware version="vmx-08" upToDate="false" />
+    </server>
+    <!-- MCP 2.0 Server State: SHUTTING_DOWN-->
+    <server id="5a32d6e4-9707-4813-a269-56ab4d989f4d" datacenterId="NA9">
+        <name>Production Web Server MCP 2</name>
+        <description>Server to host our main web application.</description>
+        <guest osCustomization="true">
+            <operatingSystem id="WIN2008S32" displayName="WIN2008S/32" family="WINDOWS" />
+            <vmTools versionStatus="CURRENT" runningStatus="RUNNING" apiVersion="9354" />
+        </guest>
+        <cpu count="2" speed="STANDARD" coresPerSocket="1" />
+        <memoryGb>4</memoryGb>
+        <disk id="c2e1f199-116e-4dbc-9960-68720b832b0a" scsiId="0" sizeGb="50" speed="STANDARD" state="NORMAL" />
+        <networkInfo networkDomainId="553f26b6-2a73-42c3-a78b-6116f11291d0">
+            <primaryNic id="5e869800-df7b-4626-bcbf-8643b8be11fd" privateIpv4="10.0.4.8" ipv6="2607:f480:1111:1282:2960:fb72:7154:6160" vlanId="bc529e20-dc6f-42ba-be20-0ffe44d1993f" vlanName="Production VLAN" state="NORMAL" />
+        </networkInfo>
+        <backup assetId="91002e08-8dc1-47a1-ad33-04f501c06f87" servicePlan="Advanced" state="NORMAL" />
+        <monitoring monitoringId="11039" servicePlan="ESSENTIALS" state="NORMAL" />
+        <softwareLabel>MSSQL2008R2S</softwareLabel>
+        <sourceImageId>3ebf3c0f-90fe-4a8b-8585-6e65b316592c</sourceImageId>
+        <createTime>2015-12-02T10:31:33.000Z</createTime>
+        <deployed>true</deployed>
+        <started>true</started>
+        <state>PENDING_CHANGE</state>
+        <progress>
+            <action>SHUTDOWN_SERVER</action>
+            <requestTime>2015-12-02T11:07:40.000Z</requestTime>
+            <userName>devuser1</userName>
+        </progress>
+        <virtualHardware version="vmx-08" upToDate="false" />
+    </server>
+    <!-- MCP 2.0 Server State: RECONFIGURING-->
+    <server id="5a32d6e4-9707-4813-a269-56ab4d989f4d" datacenterId="NA9">
+        <name>Production Web Server MCP 2</name>
+        <description>Server to host our main web application.</description>
+        <cpu count="2" speed="STANDARD" coresPerSocket="1" />
+        <memoryGb>4</memoryGb>
+        <disk id="c2e1f199-116e-4dbc-9960-68720b832b0a" scsiId="0" sizeGb="50" speed="STANDARD" state="NORMAL" />
+        <networkInfo networkDomainId="553f26b6-2a73-42c3-a78b-6116f11291d0">
+            <primaryNic id="5e869800-df7b-4626-bcbf-8643b8be11fd" privateIpv4="10.0.4.8" ipv6="2607:f480:1111:1282:2960:fb72:7154:6160" vlanId="bc529e20-dc6f-42ba-be20-0ffe44d1993f" vlanName="Production VLAN" state="NORMAL" />
+        </networkInfo>
+        <backup assetId="91002e08-8dc1-47a1-ad33-04f501c06f87" servicePlan="Advanced" state="NORMAL" />
+        <monitoring monitoringId="11039" servicePlan="ESSENTIALS" state="NORMAL" />
+        <softwareLabel>MSSQL2008R2S</softwareLabel>
+        <sourceImageId>3ebf3c0f-90fe-4a8b-8585-6e65b316592c</sourceImageId>
+        <createTime>2015-12-02T10:31:33.000Z</createTime>
+        <deployed>true</deployed>
+        <started>true</started>
+        <state>PENDING_CHANGE</state>
+        <progress>
+            <action>RECONFIGURE_SERVER</action>
+            <requestTime>2015-12-02T11:07:40.000Z</requestTime>
+            <userName>devuser1</userName>
+        </progress>
+        <guest osCustomization="true">
+            <vmTools versionStatus="CURRENT" runningStatus="RUNNING" apiVersion="9354" />
+            <operatingSystem id="WIN2008S32" displayName="WIN2008S/32" family="WINDOWS" />
+        </guest>
+        <virtualHardware version="vmx-08" upToDate="false" />
+    </server>
+    <!-- MCP 2.0 Server State: UNKNOWN - running-->
+    <server id="5a32d6e4-9707-4813-a269-56ab4d989f4d" datacenterId="NA9">
+        <name>Production Web Server MCP 2</name>
+        <description>Server to host our main web application.</description>
+        <guest osCustomization="true">
+            <operatingSystem id="WIN2008S32" displayName="WIN2008S/32" family="WINDOWS" />
+            <vmTools versionStatus="CURRENT" runningStatus="RUNNING" apiVersion="9354" />
+        </guest>
+        <cpu count="2" speed="STANDARD" coresPerSocket="1" />
+        <memoryGb>4</memoryGb>
+        <disk id="c2e1f199-116e-4dbc-9960-68720b832b0a" scsiId="0" sizeGb="50" speed="STANDARD" state="NORMAL" />
+        <networkInfo networkDomainId="553f26b6-2a73-42c3-a78b-6116f11291d0">
+            <primaryNic id="5e869800-df7b-4626-bcbf-8643b8be11fd" privateIpv4="10.0.4.8" ipv6="2607:f480:1111:1282:2960:fb72:7154:6160" vlanId="bc529e20-dc6f-42ba-be20-0ffe44d1993f" vlanName="Production VLAN" state="NORMAL" />
+        </networkInfo>
+        <backup assetId="91002e08-8dc1-47a1-ad33-04f501c06f87" servicePlan="Advanced" state="NORMAL" />
+        <monitoring monitoringId="11039" servicePlan="ESSENTIALS" state="NORMAL" />
+        <softwareLabel>MSSQL2008R2S</softwareLabel>
+        <sourceImageId>3ebf3c0f-90fe-4a8b-8585-6e65b316592c</sourceImageId>
+        <createTime>2015-12-02T10:31:33.000Z</createTime>
+        <deployed>true</deployed>
+        <started>true</started>
+        <state>UNKNOWN</state>
+        <progress>
+            <action>SHUTDOWN_SERVER</action>
+            <requestTime>2015-12-02T11:07:40.000Z</requestTime>
+            <userName>devuser1</userName>
+        </progress>
+
+        <virtualHardware version="vmx-08" upToDate="false" />
+    </server>
+    <!-- MCP 2.0 Server State: UNKNOWN-terminated-->
+    <server id="5a32d6e4-9707-4813-a269-56ab4d989f4d" datacenterId="NA9">
+        <name>Production Web Server MCP 21</name>
+        <description>Server to host our main web application.</description>
+        <cpu count="2" speed="STANDARD" coresPerSocket="1" />
+        <memoryGb>4</memoryGb>
+        <disk id="c2e1f199-116e-4dbc-9960-68720b832b0a" scsiId="0" sizeGb="50" speed="STANDARD" state="NORMAL" />
+        <networkInfo networkDomainId="553f26b6-2a73-42c3-a78b-6116f11291d0">
+            <primaryNic id="5e869800-df7b-4626-bcbf-8643b8be11fd" privateIpv4="10.0.4.8" ipv6="2607:f480:1111:1282:2960:fb72:7154:6160" vlanId="bc529e20-dc6f-42ba-be20-0ffe44d1993f" vlanName="Production VLAN" state="NORMAL" />
+        </networkInfo>
+        <backup assetId="91002e08-8dc1-47a1-ad33-04f501c06f87" servicePlan="Advanced" state="NORMAL" />
+        <monitoring monitoringId="11039" servicePlan="ESSENTIALS" state="NORMAL" />
+        <softwareLabel>MSSQL2008R2S</softwareLabel>
+        <sourceImageId>3ebf3c0f-90fe-4a8b-8585-6e65b316592c</sourceImageId>
+        <createTime>2015-12-02T10:31:33.000Z</createTime>
+        <deployed>true</deployed>
+        <started>false</started>
+        <state>UNKNOWN</state>
+        <progress>
+            <action>SHUTDOWN_SERVER</action>
+            <requestTime>2015-12-02T11:07:40.000Z</requestTime>
+            <userName>devuser1</userName>
+        </progress>
+        <virtualHardware version="vmx-08" upToDate="false" />
+        <guest osCustomization="true">
+             <operatingSystem id="WIN2008S32" displayName="WIN2008S/32"
+                              family="WINDOWS" />
+             <vmTools versionStatus="CURRENT" runningStatus="RUNNING" apiVersion="9354" />
+        </guest>
+    </server>
+    <!-- MCP 2.0 Server State: STOPPED-->
+    <server id="5a32d6e4-9707-4813-a269-56ab4d989f4d" datacenterId="NA9">
+        <name>Production Web Server MCP 2</name>
+        <description>Server to host our main web application.</description>
+        <cpu count="2" speed="STANDARD" coresPerSocket="1" />
+        <memoryGb>4</memoryGb>
+        <disk id="c2e1f199-116e-4dbc-9960-68720b832b0a" scsiId="0" sizeGb="50" speed="STANDARD" state="NORMAL" />
+        <networkInfo networkDomainId="553f26b6-2a73-42c3-a78b-6116f11291d0">
+            <primaryNic id="5e869800-df7b-4626-bcbf-8643b8be11fd" privateIpv4="10.0.4.8" ipv6="2607:f480:1111:1282:2960:fb72:7154:6160" vlanId="bc529e20-dc6f-42ba-be20-0ffe44d1993f" vlanName="Production VLAN" state="NORMAL" />
+        </networkInfo>
+        <backup assetId="91002e08-8dc1-47a1-ad33-04f501c06f87" servicePlan="Advanced" state="NORMAL" />
+        <monitoring monitoringId="11039" servicePlan="ESSENTIALS" state="NORMAL" />
+        <softwareLabel>MSSQL2008R2S</softwareLabel>
+        <sourceImageId>3ebf3c0f-90fe-4a8b-8585-6e65b316592c</sourceImageId>
+        <createTime>2015-12-02T10:31:33.000Z</createTime>
+        <deployed>true</deployed>
+        <started>false</started>
+        <state>NORMAL</state>
+        <guest osCustomization="true">
+            <vmTools versionStatus="CURRENT" runningStatus="RUNNING" apiVersion="9354" />
+            <operatingSystem id="WIN2008S32" displayName="WIN2008S/32" family="WINDOWS" />
+        </guest>
+        <virtualHardware version="vmx-08" upToDate="false" />
+    </server>
+</servers>

http://git-wip-us.apache.org/repos/asf/libcloud/blob/1bafa61d/libcloud/test/compute/fixtures/dimensiondata/2.4/server_server_NA3.xml
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/dimensiondata/2.4/server_server_NA3.xml b/libcloud/test/compute/fixtures/dimensiondata/2.4/server_server_NA3.xml
new file mode 100644
index 0000000..56e4492
--- /dev/null
+++ b/libcloud/test/compute/fixtures/dimensiondata/2.4/server_server_NA3.xml
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<servers xmlns="urn:didata.com:api:cloud:types" pageNumber="1" pageCount="2" totalCount="2" pageSize="250">
+    <!-- MCP 1.0 Server -->
+    <server id="e75ead52-692f-4314-8725-c8a4f4d13a87" datacenterId="NA3">
+        <name>Production Web Server MCP 1</name>
+        <description>nopassword0</description>
+
+        <cpu count="4" speed="STANDARD" coresPerSocket="1" />
+        <memoryGb>2</memoryGb>
+        <disk id="74f81c56-96cc-4cca-b4d7-a88f641a6ea2" scsiId="0" sizeGb="10" speed="STANDARD" state="NORMAL" />
+        <nic id="43b24e9e-c1c9-4d53-965b-89bcaa725103" privateIpv4="10.160.117.25" networkId="c550be0e-65c1-11e4-811f-005056806999" networkName="Test1" state="NORMAL" />
+        <backup assetId="5579f3a7-4c32-4cf5-8a7e-b45c36a35c10" servicePlan="Enterprise" state="NORMAL" />
+        <monitoring monitoringId="11049" servicePlan="ESSENTIALS" state="NORMAL" />
+        <sourceImageId>e9ec6eb4-4634-49de-b914-01eb74da5fb9</sourceImageId>
+        <createTime>2015-08-11T16:51:05.000Z</createTime>
+        <deployed>true</deployed>
+        <started>true</started>
+        <state>NORMAL</state>
+        <guest osCustomization="true">
+            <vmTools versionStatus="NEED_UPGRADE" runningStatus="RUNNING" apiVersion="8389" />
+            <operatingSystem id="REDHAT632" displayName="REDHAT6/32" family="UNIX" />
+        </guest>
+        <virtualHardware version="vmx-08" upToDate="false" />
+    </server>
+    <!-- MCP 2.0 Server -->
+    <server id="5a32d6e4-9707-4813-a269-56ab4d989f4d" datacenterId="NA3">
+        <name>Production Web Server MCP 2</name>
+        <description>Server to host our main web application.</description>
+
+        <cpu count="2" speed="STANDARD" coresPerSocket="1" />
+        <memoryGb>4</memoryGb>
+        <disk id="c2e1f199-116e-4dbc-9960-68720b832b0a" scsiId="0" sizeGb="50" speed="STANDARD" state="NORMAL" />
+        <networkInfo networkDomainId="553f26b6-2a73-42c3-a78b-6116f11291d0">
+            <primaryNic id="5e869800-df7b-4626-bcbf-8643b8be11fd" privateIpv4="10.0.4.8" ipv6="2607:f480:1111:1282:2960:fb72:7154:6160" vlanId="bc529e20-dc6f-42ba-be20-0ffe44d1993f" vlanName="Production VLAN" state="NORMAL" />
+        </networkInfo>
+        <backup assetId="91002e08-8dc1-47a1-ad33-04f501c06f87" servicePlan="Advanced" state="NORMAL" />
+        <monitoring monitoringId="11039" servicePlan="ESSENTIALS" state="NORMAL" />
+        <softwareLabel>MSSQL2008R2S</softwareLabel>
+        <sourceImageId>3ebf3c0f-90fe-4a8b-8585-6e65b316592c</sourceImageId>
+        <createTime>2015-12-02T10:31:33.000Z</createTime>
+        <deployed>true</deployed>
+        <started>true</started>
+        <state>PENDING_CHANGE</state>
+        <progress>
+            <action>SHUTDOWN_SERVER</action>
+            <requestTime>2015-12-02T11:07:40.000Z</requestTime>
+            <userName>devuser1</userName>
+        </progress>
+        <guest osCustomization="true">
+            <operatingSystem id="WIN2008S32" displayName="WIN2008S/32" family="WINDOWS" />
+            <vmTools versionStatus="CURRENT" runningStatus="RUNNING" apiVersion="9354" />
+        </guest>
+        <virtualHardware version="vmx-08" upToDate="false" />
+    </server>
+</servers>
+

http://git-wip-us.apache.org/repos/asf/libcloud/blob/1bafa61d/libcloud/test/compute/fixtures/dimensiondata/2.4/server_server_e75ead52_692f_4314_8725_c8a4f4d13a87.xml
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/dimensiondata/2.4/server_server_e75ead52_692f_4314_8725_c8a4f4d13a87.xml b/libcloud/test/compute/fixtures/dimensiondata/2.4/server_server_e75ead52_692f_4314_8725_c8a4f4d13a87.xml
new file mode 100644
index 0000000..c933f29
--- /dev/null
+++ b/libcloud/test/compute/fixtures/dimensiondata/2.4/server_server_e75ead52_692f_4314_8725_c8a4f4d13a87.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<server xmlns="urn:didata.com:api:cloud:types" id="e75ead52-692f-4314-8725-c8a4f4d13a87" datacenterId="NA9">
+        <name>Production Web Server</name>
+        <description>Server to host our main web application.</description>
+
+        <cpu count="2" speed="STANDARD" coresPerSocket="1" />
+        <memoryGb>4</memoryGb>
+        <disk id="c2e1f199-116e-4dbc-9960-68720b832b0a" scsiId="0" sizeGb="50" speed="STANDARD" state="NORMAL" />
+        <networkInfo networkDomainId="553f26b6-2a73-42c3-a78b-6116f11291d0">
+            <primaryNic id="5e869800-df7b-4626-bcbf-8643b8be11fd" privateIpv4="10.0.4.8" ipv6="2607:f480:1111:1282:2960:fb72:7154:6160" vlanId="bc529e20-dc6f-42ba-be20-0ffe44d1993f" vlanName="Production VLAN" state="NORMAL" />
+        </networkInfo>
+        <backup assetId="5579f3a7-4c32-4cf5-8a7e-b45c36a35c10" servicePlan="Enterprise" state="NORMAL" />
+        <monitoring monitoringId="11049" servicePlan="ESSENTIALS" state="NORMAL" />
+        <softwareLabel>MSSQL2008R2S</softwareLabel>
+        <sourceImageId>3ebf3c0f-90fe-4a8b-8585-6e65b316592c</sourceImageId>
+        <createTime>2015-12-02T10:31:33.000Z</createTime>
+        <deployed>true</deployed>
+        <started>true</started>
+        <state>PENDING_CHANGE</state>
+        <progress>
+            <action>DEPLOY_SERVER</action>
+            <requestTime>2015-12-02T11:07:40.000Z</requestTime>
+            <userName>devuser1</userName>
+        </progress>
+        <virtualHardware version="vmx-08" upToDate="false" />
+        <guest osCustomization="true">
+            <operatingSystem id="WIN2008S32" displayName="WIN2008S/32" family="WINDOWS" />
+            <vmTools versionStatus="CURRENT" runningStatus="RUNNING" apiVersion="9354" />
+        </guest>
+    </server>

http://git-wip-us.apache.org/repos/asf/libcloud/blob/1bafa61d/libcloud/test/compute/fixtures/dimensiondata/2.4/server_server_paginated.xml
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/dimensiondata/2.4/server_server_paginated.xml b/libcloud/test/compute/fixtures/dimensiondata/2.4/server_server_paginated.xml
new file mode 100644
index 0000000..575d245
--- /dev/null
+++ b/libcloud/test/compute/fixtures/dimensiondata/2.4/server_server_paginated.xml
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<servers xmlns="urn:didata.com:api:cloud:types" pageNumber="1" pageCount="2" totalCount="2" pageSize="2">
+    <!-- MCP 1.0 Server -->
+    <server id="e75ead52-692f-4314-8725-c8a4f4d13a87" datacenterId="NA1">
+        <name>Production Web Server MCP 1</name>
+        <description>nopassword0</description>
+
+        <cpu count="4" speed="STANDARD" coresPerSocket="1" />
+        <memoryGb>2</memoryGb>
+        <disk id="74f81c56-96cc-4cca-b4d7-a88f641a6ea2" scsiId="0" sizeGb="10" speed="STANDARD" state="NORMAL" />
+        <nic id="43b24e9e-c1c9-4d53-965b-89bcaa725103" privateIpv4="10.160.117.25" networkId="c550be0e-65c1-11e4-811f-005056806999" networkName="Test1" state="NORMAL" />
+        <backup assetId="5579f3a7-4c32-4cf5-8a7e-b45c36a35c10" servicePlan="Enterprise" state="NORMAL" />
+        <monitoring monitoringId="11049" servicePlan="ESSENTIALS" state="NORMAL" />
+        <sourceImageId>e9ec6eb4-4634-49de-b914-01eb74da5fb9</sourceImageId>
+        <createTime>2015-08-11T16:51:05.000Z</createTime>
+        <deployed>true</deployed>
+        <started>true</started>
+        <state>NORMAL</state>
+        <guest osCustomization="true">
+            <vmTools versionStatus="NEED_UPGRADE"
+                         runningStatus="RUNNING" apiVersion="8389" />
+             <operatingSystem id="REDHAT632" displayName="REDHAT6/32" family="UNIX" />
+        </guest>
+        <virtualHardware version="vmx-08" upToDate="false" />
+    </server>
+    <!-- MCP 2.0 Server -->
+    <server id="5a32d6e4-9707-4813-a269-56ab4d989f4d" datacenterId="NA9">
+        <name>Production Web Server MCP 2</name>
+        <description>Server to host our main web application.</description>
+
+        <cpu count="2" speed="STANDARD" coresPerSocket="1" />
+        <memoryGb>4</memoryGb>
+        <disk id="c2e1f199-116e-4dbc-9960-68720b832b0a" scsiId="0" sizeGb="50" speed="STANDARD" state="NORMAL" />
+        <networkInfo networkDomainId="553f26b6-2a73-42c3-a78b-6116f11291d0">
+            <primaryNic id="5e869800-df7b-4626-bcbf-8643b8be11fd" privateIpv4="10.0.4.8" ipv6="2607:f480:1111:1282:2960:fb72:7154:6160" vlanId="bc529e20-dc6f-42ba-be20-0ffe44d1993f" vlanName="Production VLAN" state="NORMAL" />
+        </networkInfo>
+        <backup assetId="91002e08-8dc1-47a1-ad33-04f501c06f87" servicePlan="Advanced" state="NORMAL" />
+        <monitoring monitoringId="11039" servicePlan="ESSENTIALS" state="NORMAL" />
+        <softwareLabel>MSSQL2008R2S</softwareLabel>
+        <sourceImageId>3ebf3c0f-90fe-4a8b-8585-6e65b316592c</sourceImageId>
+        <createTime>2015-12-02T10:31:33.000Z</createTime>
+        <deployed>true</deployed>
+        <started>true</started>
+        <state>PENDING_CHANGE</state>
+        <progress>
+            <action>SHUTDOWN_SERVER</action>
+            <requestTime>2015-12-02T11:07:40.000Z</requestTime>
+            <userName>devuser1</userName>
+        </progress>
+         <guest osCustomization="true">
+            <vmTools versionStatus="CURRENT" runningStatus="RUNNING"
+                         apiVersion="9354" />
+             <operatingSystem id="WIN2008S32" displayName="WIN2008S/32" family="WINDOWS" />
+        </guest>
+        <virtualHardware version="vmx-08" upToDate="false" />
+    </server>
+</servers>
+

http://git-wip-us.apache.org/repos/asf/libcloud/blob/1bafa61d/libcloud/test/compute/test_dimensiondata_v2_3.py
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/test_dimensiondata_v2_3.py b/libcloud/test/compute/test_dimensiondata_v2_3.py
index 20c544c..a342e0c 100644
--- a/libcloud/test/compute/test_dimensiondata_v2_3.py
+++ b/libcloud/test/compute/test_dimensiondata_v2_3.py
@@ -40,7 +40,7 @@ from libcloud.test.secrets import DIMENSIONDATA_PARAMS
 from libcloud.utils.xml import fixxpath, findtext, findall
 
 
-class DimensionDataTests(unittest.TestCase, TestCaseMixin):
+class DimensionData_v2_3_Tests(unittest.TestCase, TestCaseMixin):
 
     def setUp(self):
         DimensionData.connectionCls.active_api_version = '2.3'

http://git-wip-us.apache.org/repos/asf/libcloud/blob/1bafa61d/libcloud/test/compute/test_dimensiondata_v2_4.py
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/test_dimensiondata_v2_4.py b/libcloud/test/compute/test_dimensiondata_v2_4.py
index de08ad1..30f5642 100644
--- a/libcloud/test/compute/test_dimensiondata_v2_4.py
+++ b/libcloud/test/compute/test_dimensiondata_v2_4.py
@@ -40,7 +40,7 @@ from libcloud.test.secrets import DIMENSIONDATA_PARAMS
 from libcloud.utils.xml import fixxpath, findtext, findall
 
 
-class DimensionDataTests(unittest.TestCase, TestCaseMixin):
+class DimensionData_v2_4_Tests(unittest.TestCase, TestCaseMixin):
 
     def setUp(self):
         DimensionData.connectionCls.active_api_version = '2.4'
@@ -2262,18 +2262,18 @@ class DimensionDataMockHttp(StorageMockHttp, MockHttp):
     def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_server(self, method, url, body, headers):
         if url.endswith('datacenterId=NA3'):
             body = self.fixtures.load(
-                'server_server_NA3.xml')
+                '2.4/server_server_NA3.xml')
             return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
         body = self.fixtures.load(
-            'server_server.xml')
+            '2.4/server_server.xml')
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
     def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_server_PAGESIZE50(self, method, url, body, headers):
         if not url.endswith('pageSize=50'):
             raise ValueError("pageSize is not set as expected")
         body = self.fixtures.load(
-            'server_server.xml')
+            '2.4/server_server.xml')
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
     def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_server_EMPTY(self, method, url, body, headers):
@@ -2288,17 +2288,17 @@ class DimensionDataMockHttp(StorageMockHttp, MockHttp):
             return (httplib.OK, body, {}, httplib.responses[httplib.OK])
         else:
             body = self.fixtures.load(
-                'server_server_paginated.xml')
+                '2.4/server_server_paginated.xml')
             return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
     def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_server_PAGINATED(self, method, url, body, headers):
         if 'pageNumber=2' in url:
             body = self.fixtures.load(
-                'server_server.xml')
+                '2.4/server_server.xml')
             return (httplib.OK, body, {}, httplib.responses[httplib.OK])
         else:
             body = self.fixtures.load(
-                'server_server_paginated.xml')
+                '2.4/server_server_paginated.xml')
             return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
     def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_server_PAGINATEDEMPTY(self, method, url, body, headers):
@@ -2336,7 +2336,7 @@ class DimensionDataMockHttp(StorageMockHttp, MockHttp):
             else:
                 raise ValueError("Could not find in url parameters {0}:{1}".format(key, value))
         body = self.fixtures.load(
-            'server_server.xml')
+            '2.4/server_server.xml')
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
     def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_antiAffinityRule(self, method, url, body, headers):
@@ -2461,7 +2461,7 @@ class DimensionDataMockHttp(StorageMockHttp, MockHttp):
 
     def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_server_11_INPROGRESS(
             self, method, url, body, headers):
-        body = self.fixtures.load('server_GetServer.xml')
+        body = self.fixtures.load('2.4/server_GetServer.xml')
         return (httplib.BAD_REQUEST, body, {}, httplib.responses[httplib.OK])
 
     def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_networkDomain(self, method, url, body, headers):
@@ -2549,7 +2549,7 @@ class DimensionDataMockHttp(StorageMockHttp, MockHttp):
 
     def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_server_e75ead52_692f_4314_8725_c8a4f4d13a87(self, method, url, body, headers):
         body = self.fixtures.load(
-            'server_server_e75ead52_692f_4314_8725_c8a4f4d13a87.xml')
+            '2.4/server_server_e75ead52_692f_4314_8725_c8a4f4d13a87.xml')
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
     def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_deployNetworkDomain(self, method, url, body, headers):
@@ -2756,17 +2756,17 @@ class DimensionDataMockHttp(StorageMockHttp, MockHttp):
 
     def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_image_osImage(self, method, url, body, headers):
         body = self.fixtures.load(
-            'image_osImage.xml')
+            '2.4/image_osImage.xml')
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
     def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_image_osImage_c14b1a46_2428_44c1_9c1a_b20e6418d08c(self, method, url, body, headers):
         body = self.fixtures.load(
-            'image_osImage_c14b1a46_2428_44c1_9c1a_b20e6418d08c.xml')
+            '2.4/image_osImage_c14b1a46_2428_44c1_9c1a_b20e6418d08c.xml')
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
     def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_image_osImage_6b4fb0c7_a57b_4f58_b59c_9958f94f971a(self, method, url, body, headers):
         body = self.fixtures.load(
-            'image_osImage_6b4fb0c7_a57b_4f58_b59c_9958f94f971a.xml')
+            '2.4/image_osImage_6b4fb0c7_a57b_4f58_b59c_9958f94f971a.xml')
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
     def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_image_osImage_5234e5c7_01de_4411_8b6e_baeb8d91cf5d(self, method, url, body, headers):
@@ -2786,17 +2786,17 @@ class DimensionDataMockHttp(StorageMockHttp, MockHttp):
 
     def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_image_customerImage(self, method, url, body, headers):
         body = self.fixtures.load(
-            'image_customerImage.xml')
+            '2.4/image_customerImage.xml')
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
     def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_image_customerImage_5234e5c7_01de_4411_8b6e_baeb8d91cf5d(self, method, url, body, headers):
         body = self.fixtures.load(
-            'image_customerImage_5234e5c7_01de_4411_8b6e_baeb8d91cf5d.xml')
+            '2.4/image_customerImage_5234e5c7_01de_4411_8b6e_baeb8d91cf5d.xml')
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
     def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_image_customerImage_2ffa36c8_1848_49eb_b4fa_9d908775f68c(self, method, url, body, headers):
         body = self.fixtures.load(
-            'image_customerImage_2ffa36c8_1848_49eb_b4fa_9d908775f68c.xml')
+            '2.4/image_customerImage_2ffa36c8_1848_49eb_b4fa_9d908775f68c.xml')
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
     def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_image_customerImage_FAKE_IMAGE_ID(self, method, url, body, headers):
@@ -3278,5 +3278,12 @@ class DimensionDataMockHttp(StorageMockHttp, MockHttp):
 
         return httplib.OK, body, {}, httplib.responses[httplib.OK]
 
+    def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_cloneServer(
+        self, method, url, body, headers):
+        body = self.fixtures.load(
+            '2.4/server_clone_response.xml'
+        )
+        return httplib.OK, body, {}, httplib.responses[httplib.OK]
+
 if __name__ == '__main__':
     sys.exit(unittest.main())

http://git-wip-us.apache.org/repos/asf/libcloud/blob/1bafa61d/libcloud/test/loadbalancer/test_dimensiondata_v2_3.py
----------------------------------------------------------------------
diff --git a/libcloud/test/loadbalancer/test_dimensiondata_v2_3.py b/libcloud/test/loadbalancer/test_dimensiondata_v2_3.py
index c609e3d..9a406cb 100644
--- a/libcloud/test/loadbalancer/test_dimensiondata_v2_3.py
+++ b/libcloud/test/loadbalancer/test_dimensiondata_v2_3.py
@@ -29,7 +29,7 @@ from libcloud.test.file_fixtures import LoadBalancerFileFixtures
 from libcloud.test.secrets import DIMENSIONDATA_PARAMS
 
 
-class DimensionDataTests(unittest.TestCase):
+class DimensionData_v2_3_Tests(unittest.TestCase):
 
     def setUp(self):
         DimensionData.connectionCls.active_api_version = '2.3'

http://git-wip-us.apache.org/repos/asf/libcloud/blob/1bafa61d/libcloud/test/loadbalancer/test_dimensiondata_v2_4.py
----------------------------------------------------------------------
diff --git a/libcloud/test/loadbalancer/test_dimensiondata_v2_4.py b/libcloud/test/loadbalancer/test_dimensiondata_v2_4.py
index e3f7217..07f472c 100644
--- a/libcloud/test/loadbalancer/test_dimensiondata_v2_4.py
+++ b/libcloud/test/loadbalancer/test_dimensiondata_v2_4.py
@@ -29,7 +29,7 @@ from libcloud.test.file_fixtures import LoadBalancerFileFixtures
 from libcloud.test.secrets import DIMENSIONDATA_PARAMS
 
 
-class DimensionDataTests(unittest.TestCase):
+class DimensionData_v2_4_Tests(unittest.TestCase):
 
     def setUp(self):
         DimensionData.connectionCls.active_api_version = '2.4'


[15/40] libcloud git commit: Unit tests for 2.3

Posted by an...@apache.org.
http://git-wip-us.apache.org/repos/asf/libcloud/blob/bb1b8104/libcloud/test/compute/test_dimensiondata_v2_4.py
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/test_dimensiondata_v2_4.py b/libcloud/test/compute/test_dimensiondata_v2_4.py
new file mode 100644
index 0000000..de08ad1
--- /dev/null
+++ b/libcloud/test/compute/test_dimensiondata_v2_4.py
@@ -0,0 +1,3282 @@
+# 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.
+
+try:
+    from lxml import etree as ET
+except ImportError:
+    from xml.etree import ElementTree as ET
+
+import sys
+from types import GeneratorType
+from libcloud.utils.py3 import httplib
+
+from libcloud.common.types import InvalidCredsError
+from libcloud.common.dimensiondata import DimensionDataAPIException, NetworkDomainServicePlan
+from libcloud.common.dimensiondata import DimensionDataServerCpuSpecification, DimensionDataServerDisk, DimensionDataServerVMWareTools
+from libcloud.common.dimensiondata import DimensionDataTag, DimensionDataTagKey
+from libcloud.common.dimensiondata import DimensionDataIpAddress, \
+    DimensionDataIpAddressList, DimensionDataChildIpAddressList, \
+    DimensionDataPortList, DimensionDataPort, DimensionDataChildPortList
+from libcloud.common.dimensiondata import TYPES_URN
+from libcloud.compute.drivers.dimensiondata import DimensionDataNodeDriver as DimensionData
+from libcloud.compute.drivers.dimensiondata import DimensionDataNic
+from libcloud.compute.base import Node, NodeAuthPassword, NodeLocation
+from libcloud.test import MockHttp, unittest, MockRawResponse, StorageMockHttp
+from libcloud.test.compute import TestCaseMixin
+from libcloud.test.file_fixtures import ComputeFileFixtures
+from libcloud.test.secrets import DIMENSIONDATA_PARAMS
+from libcloud.utils.xml import fixxpath, findtext, findall
+
+
+class DimensionDataTests(unittest.TestCase, TestCaseMixin):
+
+    def setUp(self):
+        DimensionData.connectionCls.active_api_version = '2.4'
+        DimensionData.connectionCls.conn_classes = (None, DimensionDataMockHttp)
+        DimensionData.connectionCls.rawResponseCls = \
+            DimensionDataMockRawResponse
+        DimensionDataMockHttp.type = None
+        self.driver = DimensionData(*DIMENSIONDATA_PARAMS)
+
+    def test_invalid_region(self):
+        with self.assertRaises(ValueError):
+            DimensionData(*DIMENSIONDATA_PARAMS, region='blah')
+
+    def test_invalid_creds(self):
+        DimensionDataMockHttp.type = 'UNAUTHORIZED'
+        with self.assertRaises(InvalidCredsError):
+            self.driver.list_nodes()
+
+    def test_get_account_details(self):
+        DimensionDataMockHttp.type = None
+        ret = self.driver.connection.get_account_details()
+        self.assertEqual(ret.full_name, 'Test User')
+        self.assertEqual(ret.first_name, 'Test')
+        self.assertEqual(ret.email, 'test@example.com')
+
+    def test_list_locations_response(self):
+        DimensionDataMockHttp.type = None
+        ret = self.driver.list_locations()
+        self.assertEqual(len(ret), 5)
+        first_loc = ret[0]
+        self.assertEqual(first_loc.id, 'NA3')
+        self.assertEqual(first_loc.name, 'US - West')
+        self.assertEqual(first_loc.country, 'US')
+
+    def test_list_nodes_response(self):
+        DimensionDataMockHttp.type = None
+        ret = self.driver.list_nodes()
+        self.assertEqual(len(ret), 7)
+
+    def test_node_extras(self):
+        DimensionDataMockHttp.type = None
+        ret = self.driver.list_nodes()
+        self.assertTrue(isinstance(ret[0].extra['vmWareTools'], DimensionDataServerVMWareTools))
+        self.assertTrue(isinstance(ret[0].extra['cpu'], DimensionDataServerCpuSpecification))
+        self.assertTrue(isinstance(ret[0].extra['disks'], list))
+        self.assertTrue(isinstance(ret[0].extra['disks'][0], DimensionDataServerDisk))
+        self.assertEqual(ret[0].extra['disks'][0].size_gb, 10)
+        self.assertTrue(isinstance(ret[1].extra['disks'], list))
+        self.assertTrue(isinstance(ret[1].extra['disks'][0], DimensionDataServerDisk))
+        self.assertEqual(ret[1].extra['disks'][0].size_gb, 10)
+
+    def test_server_states(self):
+        DimensionDataMockHttp.type = None
+        ret = self.driver.list_nodes()
+        self.assertTrue(ret[0].state == 'running')
+        self.assertTrue(ret[1].state == 'starting')
+        self.assertTrue(ret[2].state == 'stopping')
+        self.assertTrue(ret[3].state == 'reconfiguring')
+        self.assertTrue(ret[4].state == 'running')
+        self.assertTrue(ret[5].state == 'terminated')
+        self.assertTrue(ret[6].state == 'stopped')
+        self.assertEqual(len(ret), 7)
+
+    def test_list_nodes_response_PAGINATED(self):
+        DimensionDataMockHttp.type = 'PAGINATED'
+        ret = self.driver.list_nodes()
+        self.assertEqual(len(ret), 9)
+
+    def test_paginated_mcp2_call_EMPTY(self):
+        # cache org
+        self.driver.connection._get_orgId()
+        DimensionDataMockHttp.type = 'EMPTY'
+        node_list_generator = self.driver.connection.paginated_request_with_orgId_api_2('server/server')
+        empty_node_list = []
+        for node_list in node_list_generator:
+            empty_node_list.extend(node_list)
+        self.assertTrue(len(empty_node_list) == 0)
+
+    def test_paginated_mcp2_call_PAGED_THEN_EMPTY(self):
+        # cache org
+        self.driver.connection._get_orgId()
+        DimensionDataMockHttp.type = 'PAGED_THEN_EMPTY'
+        node_list_generator = self.driver.connection.paginated_request_with_orgId_api_2('server/server')
+        final_node_list = []
+        for node_list in node_list_generator:
+            final_node_list.extend(node_list)
+        self.assertTrue(len(final_node_list) == 2)
+
+    def test_paginated_mcp2_call_with_page_size(self):
+        # cache org
+        self.driver.connection._get_orgId()
+        DimensionDataMockHttp.type = 'PAGESIZE50'
+        node_list_generator = self.driver.connection.paginated_request_with_orgId_api_2('server/server', page_size=50)
+        self.assertTrue(isinstance(node_list_generator, GeneratorType))
+
+    # We're making sure here the filters make it to the URL
+    # See  _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_server_ALLFILTERS for asserts
+    def test_list_nodes_response_strings_ALLFILTERS(self):
+        DimensionDataMockHttp.type = 'ALLFILTERS'
+        ret = self.driver.list_nodes(ex_location='fake_loc', ex_name='fake_name',
+                                     ex_ipv6='fake_ipv6', ex_ipv4='fake_ipv4', ex_vlan='fake_vlan',
+                                     ex_image='fake_image', ex_deployed=True,
+                                     ex_started=True, ex_state='fake_state',
+                                     ex_network='fake_network', ex_network_domain='fake_network_domain')
+        self.assertTrue(isinstance(ret, list))
+        self.assertEqual(len(ret), 7)
+
+        node = ret[3]
+        self.assertTrue(isinstance(node.extra['disks'], list))
+        self.assertTrue(isinstance(node.extra['disks'][0], DimensionDataServerDisk))
+        self.assertEqual(node.size.id, '1')
+        self.assertEqual(node.image.id, '3ebf3c0f-90fe-4a8b-8585-6e65b316592c')
+        self.assertEqual(node.image.name, 'WIN2008S/32')
+        disk = node.extra['disks'][0]
+        self.assertEqual(disk.id, "c2e1f199-116e-4dbc-9960-68720b832b0a")
+        self.assertEqual(disk.scsi_id, 0)
+        self.assertEqual(disk.size_gb, 50)
+        self.assertEqual(disk.speed, "STANDARD")
+        self.assertEqual(disk.state, "NORMAL")
+
+    def test_list_nodes_response_LOCATION(self):
+        DimensionDataMockHttp.type = None
+        ret = self.driver.list_locations()
+        first_loc = ret[0]
+        ret = self.driver.list_nodes(ex_location=first_loc)
+        for node in ret:
+            self.assertEqual(node.extra['datacenterId'], 'NA3')
+
+    def test_list_nodes_response_LOCATION_STR(self):
+        DimensionDataMockHttp.type = None
+        ret = self.driver.list_nodes(ex_location='NA3')
+        for node in ret:
+            self.assertEqual(node.extra['datacenterId'], 'NA3')
+
+    def test_list_sizes_response(self):
+        DimensionDataMockHttp.type = None
+        ret = self.driver.list_sizes()
+        self.assertEqual(len(ret), 1)
+        size = ret[0]
+        self.assertEqual(size.name, 'default')
+
+    def test_reboot_node_response(self):
+        node = Node(id='11', name=None, state=None,
+                    public_ips=None, private_ips=None, driver=self.driver)
+        ret = node.reboot()
+        self.assertTrue(ret is True)
+
+    def test_reboot_node_response_INPROGRESS(self):
+        DimensionDataMockHttp.type = 'INPROGRESS'
+        node = Node(id='11', name=None, state=None,
+                    public_ips=None, private_ips=None, driver=self.driver)
+        with self.assertRaises(DimensionDataAPIException):
+            node.reboot()
+
+    def test_destroy_node_response(self):
+        node = Node(id='11', name=None, state=None,
+                    public_ips=None, private_ips=None, driver=self.driver)
+        ret = node.destroy()
+        self.assertTrue(ret is True)
+
+    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)
+        with self.assertRaises(DimensionDataAPIException):
+            node.destroy()
+
+    def test_list_images(self):
+        images = self.driver.list_images()
+        self.assertEqual(len(images), 3)
+        self.assertEqual(images[0].name, 'RedHat 6 64-bit 2 CPU')
+        self.assertEqual(images[0].id, 'c14b1a46-2428-44c1-9c1a-b20e6418d08c')
+        self.assertEqual(images[0].extra['location'].id, 'NA9')
+        self.assertEqual(images[0].extra['cpu'].cpu_count, 2)
+        self.assertEqual(images[0].extra['OS_displayName'], 'REDHAT6/64')
+
+    def test_clean_failed_deployment_response_with_node(self):
+        node = Node(id='11', name=None, state=None,
+                    public_ips=None, private_ips=None, driver=self.driver)
+        ret = self.driver.ex_clean_failed_deployment(node)
+        self.assertTrue(ret is True)
+
+    def test_clean_failed_deployment_response_with_node_id(self):
+        node = 'e75ead52-692f-4314-8725-c8a4f4d13a87'
+        ret = self.driver.ex_clean_failed_deployment(node)
+        self.assertTrue(ret is True)
+
+    def test_ex_list_customer_images(self):
+        images = self.driver.ex_list_customer_images()
+        self.assertEqual(len(images), 3)
+        self.assertEqual(images[0].name, 'ImportedCustomerImage')
+        self.assertEqual(images[0].id, '5234e5c7-01de-4411-8b6e-baeb8d91cf5d')
+        self.assertEqual(images[0].extra['location'].id, 'NA9')
+        self.assertEqual(images[0].extra['cpu'].cpu_count, 4)
+        self.assertEqual(images[0].extra['OS_displayName'], 'REDHAT6/64')
+
+    def test_create_mcp1_node_optional_param(self):
+        root_pw = NodeAuthPassword('pass123')
+        image = self.driver.list_images()[0]
+        network = self.driver.ex_list_networks()[0]
+        cpu_spec = DimensionDataServerCpuSpecification(cpu_count='4',
+                                                       cores_per_socket='2',
+                                                       performance='STANDARD')
+        disks = [DimensionDataServerDisk(scsi_id='0', speed='HIGHPERFORMANCE')]
+        node = self.driver.create_node(name='test2', image=image, auth=root_pw,
+                                       ex_description='test2 node',
+                                       ex_network=network,
+                                       ex_is_started=False,
+                                       ex_memory_gb=8,
+                                       ex_disks=disks,
+                                       ex_cpu_specification=cpu_spec,
+                                       ex_primary_dns='10.0.0.5',
+                                       ex_secondary_dns='10.0.0.6'
+                                       )
+        self.assertEqual(node.id, 'e75ead52-692f-4314-8725-c8a4f4d13a87')
+        self.assertEqual(node.extra['status'].action, 'DEPLOY_SERVER')
+
+    def test_create_mcp1_node_response_no_pass_random_gen(self):
+        image = self.driver.list_images()[0]
+        network = self.driver.ex_list_networks()[0]
+        node = self.driver.create_node(name='test2', image=image, auth=None,
+                                       ex_description='test2 node',
+                                       ex_network=network,
+                                       ex_is_started=False)
+        self.assertEqual(node.id, 'e75ead52-692f-4314-8725-c8a4f4d13a87')
+        self.assertEqual(node.extra['status'].action, 'DEPLOY_SERVER')
+        self.assertTrue('password' in node.extra)
+
+    def test_create_mcp1_node_response_no_pass_customer_windows(self):
+        image = self.driver.ex_list_customer_images()[1]
+        network = self.driver.ex_list_networks()[0]
+        node = self.driver.create_node(name='test2', image=image, auth=None,
+                                       ex_description='test2 node', ex_network=network,
+                                       ex_is_started=False)
+        self.assertEqual(node.id, 'e75ead52-692f-4314-8725-c8a4f4d13a87')
+        self.assertEqual(node.extra['status'].action, 'DEPLOY_SERVER')
+        self.assertTrue('password' in node.extra)
+
+    def test_create_mcp1_node_response_no_pass_customer_windows_STR(self):
+        image = self.driver.ex_list_customer_images()[1].id
+        network = self.driver.ex_list_networks()[0]
+        node = self.driver.create_node(name='test2', image=image, auth=None,
+                                       ex_description='test2 node', ex_network=network,
+                                       ex_is_started=False)
+        self.assertEqual(node.id, 'e75ead52-692f-4314-8725-c8a4f4d13a87')
+        self.assertEqual(node.extra['status'].action, 'DEPLOY_SERVER')
+        self.assertTrue('password' in node.extra)
+
+    def test_create_mcp1_node_response_no_pass_customer_linux(self):
+        image = self.driver.ex_list_customer_images()[0]
+        network = self.driver.ex_list_networks()[0]
+        node = self.driver.create_node(name='test2', image=image, auth=None,
+                                       ex_description='test2 node', ex_network=network,
+                                       ex_is_started=False)
+        self.assertEqual(node.id, 'e75ead52-692f-4314-8725-c8a4f4d13a87')
+        self.assertEqual(node.extra['status'].action, 'DEPLOY_SERVER')
+        self.assertTrue('password' not in node.extra)
+
+    def test_create_mcp1_node_response_no_pass_customer_linux_STR(self):
+        image = self.driver.ex_list_customer_images()[0].id
+        network = self.driver.ex_list_networks()[0]
+        node = self.driver.create_node(name='test2', image=image, auth=None,
+                                       ex_description='test2 node', ex_network=network,
+                                       ex_is_started=False)
+        self.assertEqual(node.id, 'e75ead52-692f-4314-8725-c8a4f4d13a87')
+        self.assertEqual(node.extra['status'].action, 'DEPLOY_SERVER')
+        self.assertTrue('password' not in node.extra)
+
+    def test_create_mcp1_node_response_STR(self):
+        rootPw = 'pass123'
+        image = self.driver.list_images()[0].id
+        network = self.driver.ex_list_networks()[0].id
+        node = self.driver.create_node(name='test2', image=image, auth=rootPw,
+                                       ex_description='test2 node', ex_network=network,
+                                       ex_is_started=False)
+        self.assertEqual(node.id, 'e75ead52-692f-4314-8725-c8a4f4d13a87')
+        self.assertEqual(node.extra['status'].action, 'DEPLOY_SERVER')
+
+    def test_create_node_response_network_domain(self):
+        rootPw = NodeAuthPassword('pass123')
+        location = self.driver.ex_get_location_by_id('NA9')
+        image = self.driver.list_images(location=location)[0]
+        network_domain = self.driver.ex_list_network_domains(location=location)[0]
+        vlan = self.driver.ex_list_vlans(location=location)[0]
+        cpu = DimensionDataServerCpuSpecification(
+            cpu_count=4,
+            cores_per_socket=1,
+            performance='HIGHPERFORMANCE'
+        )
+        node = self.driver.create_node(name='test2', image=image, auth=rootPw,
+                                       ex_description='test2 node',
+                                       ex_network_domain=network_domain,
+                                       ex_vlan=vlan,
+                                       ex_is_started=False, ex_cpu_specification=cpu,
+                                       ex_memory_gb=4)
+        self.assertEqual(node.id, 'e75ead52-692f-4314-8725-c8a4f4d13a87')
+        self.assertEqual(node.extra['status'].action, 'DEPLOY_SERVER')
+
+    def test_create_node_response_network_domain_STR(self):
+        rootPw = NodeAuthPassword('pass123')
+        location = self.driver.ex_get_location_by_id('NA9')
+        image = self.driver.list_images(location=location)[0]
+        network_domain = self.driver.ex_list_network_domains(location=location)[0].id
+        vlan = self.driver.ex_list_vlans(location=location)[0].id
+        cpu = DimensionDataServerCpuSpecification(
+            cpu_count=4,
+            cores_per_socket=1,
+            performance='HIGHPERFORMANCE'
+        )
+        node = self.driver.create_node(name='test2', image=image, auth=rootPw,
+                                       ex_description='test2 node',
+                                       ex_network_domain=network_domain,
+                                       ex_vlan=vlan,
+                                       ex_is_started=False, ex_cpu_specification=cpu,
+                                       ex_memory_gb=4)
+        self.assertEqual(node.id, 'e75ead52-692f-4314-8725-c8a4f4d13a87')
+        self.assertEqual(node.extra['status'].action, 'DEPLOY_SERVER')
+
+    def test_create_mcp1_node_no_network(self):
+        rootPw = NodeAuthPassword('pass123')
+        image = self.driver.list_images()[0]
+        with self.assertRaises(InvalidRequestError):
+            self.driver.create_node(name='test2',
+                                    image=image,
+                                    auth=rootPw,
+                                    ex_description='test2 node',
+                                    ex_network=None,
+                                    ex_is_started=False)
+
+    def test_create_node_mcp1_ipv4(self):
+        rootPw = NodeAuthPassword('pass123')
+        image = self.driver.list_images()[0]
+        node = self.driver.create_node(name='test2',
+                                       image=image,
+                                       auth=rootPw,
+                                       ex_description='test2 node',
+                                       ex_network='fakenetwork',
+                                       ex_primary_ipv4='10.0.0.1',
+                                       ex_is_started=False)
+        self.assertEqual(node.id, 'e75ead52-692f-4314-8725-c8a4f4d13a87')
+        self.assertEqual(node.extra['status'].action, 'DEPLOY_SERVER')
+
+    def test_create_node_mcp1_network(self):
+        rootPw = NodeAuthPassword('pass123')
+        image = self.driver.list_images()[0]
+        node = self.driver.create_node(name='test2',
+                                       image=image,
+                                       auth=rootPw,
+                                       ex_description='test2 node',
+                                       ex_network='fakenetwork',
+                                       ex_is_started=False)
+        self.assertEqual(node.id, 'e75ead52-692f-4314-8725-c8a4f4d13a87')
+        self.assertEqual(node.extra['status'].action, 'DEPLOY_SERVER')
+
+    def test_create_node_mcp2_vlan(self):
+        rootPw = NodeAuthPassword('pass123')
+        image = self.driver.list_images()[0]
+        node = self.driver.create_node(name='test2',
+                                       image=image,
+                                       auth=rootPw,
+                                       ex_description='test2 node',
+                                       ex_network_domain='fakenetworkdomain',
+                                       ex_vlan='fakevlan',
+                                       ex_is_started=False)
+        self.assertEqual(node.id, 'e75ead52-692f-4314-8725-c8a4f4d13a87')
+        self.assertEqual(node.extra['status'].action, 'DEPLOY_SERVER')
+
+    def test_create_node_mcp2_ipv4(self):
+        rootPw = NodeAuthPassword('pass123')
+        image = self.driver.list_images()[0]
+        node = self.driver.create_node(name='test2',
+                                       image=image,
+                                       auth=rootPw,
+                                       ex_description='test2 node',
+                                       ex_network_domain='fakenetworkdomain',
+                                       ex_primary_ipv4='10.0.0.1',
+                                       ex_is_started=False)
+        self.assertEqual(node.id, 'e75ead52-692f-4314-8725-c8a4f4d13a87')
+        self.assertEqual(node.extra['status'].action, 'DEPLOY_SERVER')
+
+    def test_create_node_network_domain_no_vlan_or_ipv4(self):
+        rootPw = NodeAuthPassword('pass123')
+        image = self.driver.list_images()[0]
+        with self.assertRaises(ValueError):
+            self.driver.create_node(name='test2',
+                                    image=image,
+                                    auth=rootPw,
+                                    ex_description='test2 node',
+                                    ex_network_domain='fake_network_domain',
+                                    ex_is_started=False)
+
+    def test_create_node_response(self):
+        rootPw = NodeAuthPassword('pass123')
+        image = self.driver.list_images()[0]
+        node = self.driver.create_node(
+            name='test3',
+            image=image,
+            auth=rootPw,
+            ex_network_domain='fakenetworkdomain',
+            ex_primary_nic_vlan='fakevlan'
+        )
+        self.assertEqual(node.id, 'e75ead52-692f-4314-8725-c8a4f4d13a87')
+        self.assertEqual(node.extra['status'].action, 'DEPLOY_SERVER')
+
+    def test_create_node_ms_time_zone(self):
+        rootPw = NodeAuthPassword('pass123')
+        image = self.driver.list_images()[0]
+        node = self.driver.create_node(
+            name='test3',
+            image=image,
+            auth=rootPw,
+            ex_network_domain='fakenetworkdomain',
+            ex_primary_nic_vlan='fakevlan',
+            ex_microsoft_time_zone='040'
+        )
+        self.assertEqual(node.id, 'e75ead52-692f-4314-8725-c8a4f4d13a87')
+        self.assertEqual(node.extra['status'].action, 'DEPLOY_SERVER')
+
+    def test_create_node_ambigious_mcps_fail(self):
+        rootPw = NodeAuthPassword('pass123')
+        image = self.driver.list_images()[0]
+        with self.assertRaises(ValueError):
+            self.driver.create_node(
+                name='test3',
+                image=image,
+                auth=rootPw,
+                ex_network_domain='fakenetworkdomain',
+                ex_network='fakenetwork',
+                ex_primary_nic_vlan='fakevlan'
+            )
+
+    def test_create_node_no_network_domain_fail(self):
+        rootPw = NodeAuthPassword('pass123')
+        image = self.driver.list_images()[0]
+        with self.assertRaises(ValueError):
+            self.driver.create_node(
+                name='test3',
+                image=image,
+                auth=rootPw,
+                ex_primary_nic_vlan='fakevlan'
+            )
+
+    def test_create_node_no_primary_nic_fail(self):
+        rootPw = NodeAuthPassword('pass123')
+        image = self.driver.list_images()[0]
+        with self.assertRaises(ValueError):
+            self.driver.create_node(
+                name='test3',
+                image=image,
+                auth=rootPw,
+                ex_network_domain='fakenetworkdomain'
+            )
+
+    def test_create_node_primary_vlan_nic(self):
+        rootPw = NodeAuthPassword('pass123')
+        image = self.driver.list_images()[0]
+        node = self.driver.create_node(
+            name='test3',
+            image=image,
+            auth=rootPw,
+            ex_network_domain='fakenetworkdomain',
+            ex_primary_nic_vlan='fakevlan',
+            ex_primary_nic_network_adapter='v1000'
+        )
+        self.assertEqual(node.id, 'e75ead52-692f-4314-8725-c8a4f4d13a87')
+        self.assertEqual(node.extra['status'].action, 'DEPLOY_SERVER')
+
+    def test_create_node_primary_ipv4(self):
+        rootPw = 'pass123'
+        image = self.driver.list_images()[0]
+        node = self.driver.create_node(
+            name='test3',
+            image=image,
+            auth=rootPw,
+            ex_network_domain='fakenetworkdomain',
+            ex_primary_nic_private_ipv4='10.0.0.1'
+        )
+        self.assertEqual(node.id, 'e75ead52-692f-4314-8725-c8a4f4d13a87')
+        self.assertEqual(node.extra['status'].action, 'DEPLOY_SERVER')
+
+    def test_create_node_both_primary_nic_and_vlan_fail(self):
+        rootPw = NodeAuthPassword('pass123')
+        image = self.driver.list_images()[0]
+        with self.assertRaises(ValueError):
+            self.driver.create_node(
+                name='test3',
+                image=image,
+                auth=rootPw,
+                ex_network_domain='fakenetworkdomain',
+                ex_primary_nic_private_ipv4='10.0.0.1',
+                ex_primary_nic_vlan='fakevlan'
+            )
+
+    def test_create_node_cpu_specification(self):
+        rootPw = NodeAuthPassword('pass123')
+        image = self.driver.list_images()[0]
+        cpu_spec = DimensionDataServerCpuSpecification(cpu_count='4',
+                                                       cores_per_socket='2',
+                                                       performance='STANDARD')
+        node = self.driver.create_node(name='test2',
+                                       image=image,
+                                       auth=rootPw,
+                                       ex_description='test2 node',
+                                       ex_network_domain='fakenetworkdomain',
+                                       ex_primary_nic_private_ipv4='10.0.0.1',
+                                       ex_is_started=False,
+                                       ex_cpu_specification=cpu_spec)
+        self.assertEqual(node.id, 'e75ead52-692f-4314-8725-c8a4f4d13a87')
+        self.assertEqual(node.extra['status'].action, 'DEPLOY_SERVER')
+
+    def test_create_node_memory(self):
+        rootPw = NodeAuthPassword('pass123')
+        image = self.driver.list_images()[0]
+
+        node = self.driver.create_node(name='test2',
+                                       image=image,
+                                       auth=rootPw,
+                                       ex_description='test2 node',
+                                       ex_network_domain='fakenetworkdomain',
+                                       ex_primary_nic_private_ipv4='10.0.0.1',
+                                       ex_is_started=False,
+                                       ex_memory_gb=8)
+        self.assertEqual(node.id, 'e75ead52-692f-4314-8725-c8a4f4d13a87')
+        self.assertEqual(node.extra['status'].action, 'DEPLOY_SERVER')
+
+    def test_create_node_disks(self):
+        rootPw = NodeAuthPassword('pass123')
+        image = self.driver.list_images()[0]
+        disks = [DimensionDataServerDisk(scsi_id='0', speed='HIGHPERFORMANCE')]
+        node = self.driver.create_node(name='test2',
+                                       image=image,
+                                       auth=rootPw,
+                                       ex_description='test2 node',
+                                       ex_network_domain='fakenetworkdomain',
+                                       ex_primary_nic_private_ipv4='10.0.0.1',
+                                       ex_is_started=False,
+                                       ex_disks=disks)
+        self.assertEqual(node.id, 'e75ead52-692f-4314-8725-c8a4f4d13a87')
+        self.assertEqual(node.extra['status'].action, 'DEPLOY_SERVER')
+
+    def test_create_node_disks_fail(self):
+        root_pw = NodeAuthPassword('pass123')
+        image = self.driver.list_images()[0]
+        disks = 'blah'
+        with self.assertRaises(TypeError):
+            self.driver.create_node(name='test2',
+                                    image=image,
+                                    auth=root_pw,
+                                    ex_description='test2 node',
+                                    ex_network_domain='fakenetworkdomain',
+                                    ex_primary_nic_private_ipv4='10.0.0.1',
+                                    ex_is_started=False,
+                                    ex_disks=disks)
+
+    def test_create_node_ipv4_gateway(self):
+        rootPw = NodeAuthPassword('pass123')
+        image = self.driver.list_images()[0]
+        node = self.driver.create_node(name='test2',
+                                       image=image,
+                                       auth=rootPw,
+                                       ex_description='test2 node',
+                                       ex_network_domain='fakenetworkdomain',
+                                       ex_primary_nic_private_ipv4='10.0.0.1',
+                                       ex_is_started=False,
+                                       ex_ipv4_gateway='10.2.2.2')
+        self.assertEqual(node.id, 'e75ead52-692f-4314-8725-c8a4f4d13a87')
+        self.assertEqual(node.extra['status'].action, 'DEPLOY_SERVER')
+
+    def test_create_node_network_domain_no_vlan_no_ipv4_fail(self):
+        rootPw = NodeAuthPassword('pass123')
+        image = self.driver.list_images()[0]
+        with self.assertRaises(ValueError):
+            self.driver.create_node(name='test2',
+                                    image=image,
+                                    auth=rootPw,
+                                    ex_description='test2 node',
+                                    ex_network_domain='fake_network_domain',
+                                    ex_is_started=False)
+
+    def test_create_node_mcp2_additional_nics_legacy(self):
+        rootPw = NodeAuthPassword('pass123')
+        image = self.driver.list_images()[0]
+        additional_vlans = ['fakevlan1', 'fakevlan2']
+        additional_ipv4 = ['10.0.0.2', '10.0.0.3']
+        node = self.driver.create_node(
+            name='test2',
+            image=image,
+            auth=rootPw,
+            ex_description='test2 node',
+            ex_network_domain='fakenetworkdomain',
+            ex_primary_ipv4='10.0.0.1',
+            ex_additional_nics_vlan=additional_vlans,
+            ex_additional_nics_ipv4=additional_ipv4,
+            ex_is_started=False)
+        self.assertEqual(node.id, 'e75ead52-692f-4314-8725-c8a4f4d13a87')
+        self.assertEqual(node.extra['status'].action, 'DEPLOY_SERVER')
+
+    def test_create_node_bad_additional_nics_ipv4(self):
+        rootPw = NodeAuthPassword('pass123')
+        image = self.driver.list_images()[0]
+        with self.assertRaises(TypeError):
+            self.driver.create_node(name='test2',
+                                    image=image,
+                                    auth=rootPw,
+                                    ex_description='test2 node',
+                                    ex_network_domain='fake_network_domain',
+                                    ex_vlan='fake_vlan',
+                                    ex_additional_nics_ipv4='badstring',
+                                    ex_is_started=False)
+
+    def test_create_node_additional_nics(self):
+        root_pw = NodeAuthPassword('pass123')
+        image = self.driver.list_images()[0]
+        nic1 = DimensionDataNic(vlan='fake_vlan',
+                                network_adapter_name='v1000')
+        nic2 = DimensionDataNic(private_ip_v4='10.1.1.2',
+                                network_adapter_name='v1000')
+        additional_nics = [nic1, nic2]
+
+        node = self.driver.create_node(name='test2',
+                                       image=image,
+                                       auth=root_pw,
+                                       ex_description='test2 node',
+                                       ex_network_domain='fakenetworkdomain',
+                                       ex_primary_nic_private_ipv4='10.0.0.1',
+                                       ex_additional_nics=additional_nics,
+                                       ex_is_started=False)
+
+        self.assertEqual(node.id, 'e75ead52-692f-4314-8725-c8a4f4d13a87')
+        self.assertEqual(node.extra['status'].action, 'DEPLOY_SERVER')
+
+    def test_create_node_additional_nics_vlan_ipv4_coexist_fail(self):
+        root_pw = NodeAuthPassword('pass123')
+        image = self.driver.list_images()[0]
+        nic1 = DimensionDataNic(private_ip_v4='10.1.1.1', vlan='fake_vlan',
+                                network_adapter_name='v1000')
+        nic2 = DimensionDataNic(private_ip_v4='10.1.1.2', vlan='fake_vlan2',
+                                network_adapter_name='v1000')
+        additional_nics = [nic1, nic2]
+        with self.assertRaises(ValueError):
+            self.driver.create_node(name='test2',
+                                    image=image,
+                                    auth=root_pw,
+                                    ex_description='test2 node',
+                                    ex_network_domain='fakenetworkdomain',
+                                    ex_primary_nic_private_ipv4='10.0.0.1',
+                                    ex_additional_nics=additional_nics,
+                                    ex_is_started=False
+                                    )
+
+    def test_create_node_additional_nics_invalid_input_fail(self):
+        root_pw = NodeAuthPassword('pass123')
+        image = self.driver.list_images()[0]
+        additional_nics = 'blah'
+        with self.assertRaises(TypeError):
+            self.driver.create_node(name='test2',
+                                    image=image,
+                                    auth=root_pw,
+                                    ex_description='test2 node',
+                                    ex_network_domain='fakenetworkdomain',
+                                    ex_primary_nic_private_ipv4='10.0.0.1',
+                                    ex_additional_nics=additional_nics,
+                                    ex_is_started=False
+                                    )
+
+    def test_create_node_additional_nics_vlan_ipv4_not_exist_fail(self):
+        root_pw = NodeAuthPassword('pass123')
+        image = self.driver.list_images()[0]
+        nic1 = DimensionDataNic(network_adapter_name='v1000')
+        nic2 = DimensionDataNic(network_adapter_name='v1000')
+        additional_nics = [nic1, nic2]
+        with self.assertRaises(ValueError):
+            self.driver.create_node(name='test2',
+                                    image=image,
+                                    auth=root_pw,
+                                    ex_description='test2 node',
+                                    ex_network_domain='fakenetworkdomain',
+                                    ex_primary_nic_private_ipv4='10.0.0.1',
+                                    ex_additional_nics=additional_nics,
+                                    ex_is_started=False)
+
+    def test_create_node_bad_additional_nics_vlan(self):
+        rootPw = NodeAuthPassword('pass123')
+        image = self.driver.list_images()[0]
+        with self.assertRaises(TypeError):
+            self.driver.create_node(name='test2',
+                                    image=image,
+                                    auth=rootPw,
+                                    ex_description='test2 node',
+                                    ex_network_domain='fake_network_domain',
+                                    ex_vlan='fake_vlan',
+                                    ex_additional_nics_vlan='badstring',
+                                    ex_is_started=False)
+
+    def test_create_node_mcp2_indicate_dns(self):
+        rootPw = NodeAuthPassword('pass123')
+        image = self.driver.list_images()[0]
+        node = self.driver.create_node(name='test2',
+                                       image=image,
+                                       auth=rootPw,
+                                       ex_description='test node dns',
+                                       ex_network_domain='fakenetworkdomain',
+                                       ex_primary_ipv4='10.0.0.1',
+                                       ex_primary_dns='8.8.8.8',
+                                       ex_secondary_dns='8.8.4.4',
+                                       ex_is_started=False)
+        self.assertEqual(node.id, 'e75ead52-692f-4314-8725-c8a4f4d13a87')
+        self.assertEqual(node.extra['status'].action, 'DEPLOY_SERVER')
+
+    def test_ex_shutdown_graceful(self):
+        node = Node(id='11', name=None, state=None,
+                    public_ips=None, private_ips=None, driver=self.driver)
+        ret = self.driver.ex_shutdown_graceful(node)
+        self.assertTrue(ret is True)
+
+    def test_ex_shutdown_graceful_INPROGRESS(self):
+        DimensionDataMockHttp.type = 'INPROGRESS'
+        node = Node(id='11', name=None, state=None,
+                    public_ips=None, private_ips=None, driver=self.driver)
+        with self.assertRaises(DimensionDataAPIException):
+            self.driver.ex_shutdown_graceful(node)
+
+    def test_ex_start_node(self):
+        node = Node(id='11', name=None, state=None,
+                    public_ips=None, private_ips=None, driver=self.driver)
+        ret = self.driver.ex_start_node(node)
+        self.assertTrue(ret is True)
+
+    def test_ex_start_node_INPROGRESS(self):
+        DimensionDataMockHttp.type = 'INPROGRESS'
+        node = Node(id='11', name=None, state=None,
+                    public_ips=None, private_ips=None, driver=self.driver)
+        with self.assertRaises(DimensionDataAPIException):
+            self.driver.ex_start_node(node)
+
+    def test_ex_power_off(self):
+        node = Node(id='11', name=None, state=None,
+                    public_ips=None, private_ips=None, driver=self.driver)
+        ret = self.driver.ex_power_off(node)
+        self.assertTrue(ret is True)
+
+    def test_ex_update_vm_tools(self):
+        node = Node(id='11', name=None, state=None,
+                    public_ips=None, private_ips=None, driver=self.driver)
+        ret = self.driver.ex_update_vm_tools(node)
+        self.assertTrue(ret is True)
+
+    def test_ex_power_off_INPROGRESS(self):
+        DimensionDataMockHttp.type = 'INPROGRESS'
+        node = Node(id='11', name=None, state='STOPPING',
+                    public_ips=None, private_ips=None, driver=self.driver)
+
+        with self.assertRaises(DimensionDataAPIException):
+            self.driver.ex_power_off(node)
+
+    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_attach_node_to_vlan(self):
+        node = self.driver.ex_get_node_by_id('e75ead52-692f-4314-8725-c8a4f4d13a87')
+        vlan = self.driver.ex_get_vlan('0e56433f-d808-4669-821d-812769517ff8')
+        ret = self.driver.ex_attach_node_to_vlan(node, vlan)
+        self.assertTrue(ret is True)
+
+    def test_ex_destroy_nic(self):
+        node = self.driver.ex_destroy_nic('a202e51b-41c0-4cfc-add0-b1c62fc0ecf6')
+        self.assertTrue(node)
+
+    def test_list_networks(self):
+        nets = self.driver.list_networks()
+        self.assertEqual(nets[0].name, 'test-net1')
+        self.assertTrue(isinstance(nets[0].location, NodeLocation))
+
+    def test_ex_create_network(self):
+        location = self.driver.ex_get_location_by_id('NA9')
+        net = self.driver.ex_create_network(location, "Test Network", "test")
+        self.assertEqual(net.id, "208e3a8e-9d2f-11e2-b29c-001517c4643e")
+        self.assertEqual(net.name, "Test Network")
+
+    def test_ex_create_network_NO_DESCRIPTION(self):
+        location = self.driver.ex_get_location_by_id('NA9')
+        net = self.driver.ex_create_network(location, "Test Network")
+        self.assertEqual(net.id, "208e3a8e-9d2f-11e2-b29c-001517c4643e")
+        self.assertEqual(net.name, "Test Network")
+
+    def test_ex_delete_network(self):
+        net = self.driver.ex_list_networks()[0]
+        result = self.driver.ex_delete_network(net)
+        self.assertTrue(result)
+
+    def test_ex_rename_network(self):
+        net = self.driver.ex_list_networks()[0]
+        result = self.driver.ex_rename_network(net, "barry")
+        self.assertTrue(result)
+
+    def test_ex_create_network_domain(self):
+        location = self.driver.ex_get_location_by_id('NA9')
+        plan = NetworkDomainServicePlan.ADVANCED
+        net = self.driver.ex_create_network_domain(location=location,
+                                                   name='test',
+                                                   description='test',
+                                                   service_plan=plan)
+        self.assertEqual(net.name, 'test')
+        self.assertTrue(net.id, 'f14a871f-9a25-470c-aef8-51e13202e1aa')
+
+    def test_ex_create_network_domain_NO_DESCRIPTION(self):
+        location = self.driver.ex_get_location_by_id('NA9')
+        plan = NetworkDomainServicePlan.ADVANCED
+        net = self.driver.ex_create_network_domain(location=location,
+                                                   name='test',
+                                                   service_plan=plan)
+        self.assertEqual(net.name, 'test')
+        self.assertTrue(net.id, 'f14a871f-9a25-470c-aef8-51e13202e1aa')
+
+    def test_ex_get_network_domain(self):
+        net = self.driver.ex_get_network_domain('8cdfd607-f429-4df6-9352-162cfc0891be')
+        self.assertEqual(net.id, '8cdfd607-f429-4df6-9352-162cfc0891be')
+        self.assertEqual(net.description, 'test2')
+        self.assertEqual(net.name, 'test')
+
+    def test_ex_update_network_domain(self):
+        net = self.driver.ex_get_network_domain('8cdfd607-f429-4df6-9352-162cfc0891be')
+        net.name = 'new name'
+        net2 = self.driver.ex_update_network_domain(net)
+        self.assertEqual(net2.name, 'new name')
+
+    def test_ex_delete_network_domain(self):
+        net = self.driver.ex_get_network_domain('8cdfd607-f429-4df6-9352-162cfc0891be')
+        result = self.driver.ex_delete_network_domain(net)
+        self.assertTrue(result)
+
+    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, 'Aurora')
+        self.assertTrue(isinstance(nets[0].location, NodeLocation))
+
+    def test_ex_list_network_domains_ALLFILTERS(self):
+        DimensionDataMockHttp.type = 'ALLFILTERS'
+        nets = self.driver.ex_list_network_domains(location='fake_location', name='fake_name',
+                                                   service_plan='fake_plan', state='fake_state')
+        self.assertEqual(nets[0].name, 'Aurora')
+        self.assertTrue(isinstance(nets[0].location, NodeLocation))
+
+    def test_ex_list_vlans(self):
+        vlans = self.driver.ex_list_vlans()
+        self.assertEqual(vlans[0].name, "Primary")
+
+    def test_ex_list_vlans_ALLFILTERS(self):
+        DimensionDataMockHttp.type = 'ALLFILTERS'
+        vlans = self.driver.ex_list_vlans(location='fake_location', network_domain='fake_network_domain',
+                                          name='fake_name', ipv4_address='fake_ipv4', ipv6_address='fake_ipv6', state='fake_state')
+        self.assertEqual(vlans[0].name, "Primary")
+
+    def test_ex_create_vlan(self,):
+        net = self.driver.ex_get_network_domain('8cdfd607-f429-4df6-9352-162cfc0891be')
+        vlan = self.driver.ex_create_vlan(network_domain=net,
+                                          name='test',
+                                          private_ipv4_base_address='10.3.4.0',
+                                          private_ipv4_prefix_size='24',
+                                          description='test vlan')
+        self.assertEqual(vlan.id, '0e56433f-d808-4669-821d-812769517ff8')
+
+    def test_ex_create_vlan_NO_DESCRIPTION(self,):
+        net = self.driver.ex_get_network_domain('8cdfd607-f429-4df6-9352-162cfc0891be')
+        vlan = self.driver.ex_create_vlan(network_domain=net,
+                                          name='test',
+                                          private_ipv4_base_address='10.3.4.0',
+                                          private_ipv4_prefix_size='24')
+        self.assertEqual(vlan.id, '0e56433f-d808-4669-821d-812769517ff8')
+
+    def test_ex_get_vlan(self):
+        vlan = self.driver.ex_get_vlan('0e56433f-d808-4669-821d-812769517ff8')
+        self.assertEqual(vlan.id, '0e56433f-d808-4669-821d-812769517ff8')
+        self.assertEqual(vlan.description, 'test2')
+        self.assertEqual(vlan.status, 'NORMAL')
+        self.assertEqual(vlan.name, 'Production VLAN')
+        self.assertEqual(vlan.private_ipv4_range_address, '10.0.3.0')
+        self.assertEqual(vlan.private_ipv4_range_size, 24)
+        self.assertEqual(vlan.ipv6_range_size, 64)
+        self.assertEqual(vlan.ipv6_range_address, '2607:f480:1111:1153:0:0:0:0')
+        self.assertEqual(vlan.ipv4_gateway, '10.0.3.1')
+        self.assertEqual(vlan.ipv6_gateway, '2607:f480:1111:1153:0:0:0:1')
+
+    def test_ex_wait_for_state(self):
+        self.driver.ex_wait_for_state('NORMAL',
+                                      self.driver.ex_get_vlan,
+                                      vlan_id='0e56433f-d808-4669-821d-812769517ff8')
+
+    def test_ex_wait_for_state_NODE(self):
+        self.driver.ex_wait_for_state('running',
+                                      self.driver.ex_get_node_by_id,
+                                      id='e75ead52-692f-4314-8725-c8a4f4d13a87')
+
+    def test_ex_wait_for_state_FAIL(self):
+        with self.assertRaises(DimensionDataAPIException) as context:
+            self.driver.ex_wait_for_state('starting',
+                                          self.driver.ex_get_node_by_id,
+                                          id='e75ead52-692f-4314-8725-c8a4f4d13a87',
+                                          timeout=2
+                                          )
+        self.assertEqual(context.exception.code, 'running')
+        self.assertTrue('timed out' in context.exception.msg)
+
+    def test_ex_update_vlan(self):
+        vlan = self.driver.ex_get_vlan('0e56433f-d808-4669-821d-812769517ff8')
+        vlan.name = 'new name'
+        vlan2 = self.driver.ex_update_vlan(vlan)
+        self.assertEqual(vlan2.name, 'new name')
+
+    def test_ex_delete_vlan(self):
+        vlan = self.driver.ex_get_vlan('0e56433f-d808-4669-821d-812769517ff8')
+        result = self.driver.ex_delete_vlan(vlan)
+        self.assertTrue(result)
+
+    def test_ex_expand_vlan(self):
+        vlan = self.driver.ex_get_vlan('0e56433f-d808-4669-821d-812769517ff8')
+        vlan.private_ipv4_range_size = '23'
+        vlan = self.driver.ex_expand_vlan(vlan)
+        self.assertEqual(vlan.private_ipv4_range_size, '23')
+
+    def test_ex_add_public_ip_block_to_network_domain(self):
+        net = self.driver.ex_get_network_domain('8cdfd607-f429-4df6-9352-162cfc0891be')
+        block = self.driver.ex_add_public_ip_block_to_network_domain(net)
+        self.assertEqual(block.id, '9945dc4a-bdce-11e4-8c14-b8ca3a5d9ef8')
+
+    def test_ex_list_public_ip_blocks(self):
+        net = self.driver.ex_get_network_domain('8cdfd607-f429-4df6-9352-162cfc0891be')
+        blocks = self.driver.ex_list_public_ip_blocks(net)
+        self.assertEqual(blocks[0].base_ip, '168.128.4.18')
+        self.assertEqual(blocks[0].size, '2')
+        self.assertEqual(blocks[0].id, '9945dc4a-bdce-11e4-8c14-b8ca3a5d9ef8')
+        self.assertEqual(blocks[0].location.id, 'NA9')
+        self.assertEqual(blocks[0].network_domain.id, net.id)
+
+    def test_ex_get_public_ip_block(self):
+        net = self.driver.ex_get_network_domain('8cdfd607-f429-4df6-9352-162cfc0891be')
+        block = self.driver.ex_get_public_ip_block('9945dc4a-bdce-11e4-8c14-b8ca3a5d9ef8')
+        self.assertEqual(block.base_ip, '168.128.4.18')
+        self.assertEqual(block.size, '2')
+        self.assertEqual(block.id, '9945dc4a-bdce-11e4-8c14-b8ca3a5d9ef8')
+        self.assertEqual(block.location.id, 'NA9')
+        self.assertEqual(block.network_domain.id, net.id)
+
+    def test_ex_delete_public_ip_block(self):
+        block = self.driver.ex_get_public_ip_block('9945dc4a-bdce-11e4-8c14-b8ca3a5d9ef8')
+        result = self.driver.ex_delete_public_ip_block(block)
+        self.assertTrue(result)
+
+    def test_ex_list_firewall_rules(self):
+        net = self.driver.ex_get_network_domain('8cdfd607-f429-4df6-9352-162cfc0891be')
+        rules = self.driver.ex_list_firewall_rules(net)
+        self.assertEqual(rules[0].id, '756cba02-b0bc-48f4-aea5-9445870b6148')
+        self.assertEqual(rules[0].network_domain.id, '8cdfd607-f429-4df6-9352-162cfc0891be')
+        self.assertEqual(rules[0].name, 'CCDEFAULT.BlockOutboundMailIPv4')
+        self.assertEqual(rules[0].action, 'DROP')
+        self.assertEqual(rules[0].ip_version, 'IPV4')
+        self.assertEqual(rules[0].protocol, 'TCP')
+        self.assertEqual(rules[0].source.ip_address, 'ANY')
+        self.assertTrue(rules[0].source.any_ip)
+        self.assertTrue(rules[0].destination.any_ip)
+
+    def test_ex_create_firewall_rule(self):
+        net = self.driver.ex_get_network_domain('8cdfd607-f429-4df6-9352-162cfc0891be')
+        rules = self.driver.ex_list_firewall_rules(net)
+        rule = self.driver.ex_create_firewall_rule(net, rules[0], 'FIRST')
+        self.assertEqual(rule.id, 'd0a20f59-77b9-4f28-a63b-e58496b73a6c')
+
+    def test_ex_create_firewall_rule_with_specific_source_ip(self):
+        net = self.driver.ex_get_network_domain('8cdfd607-f429-4df6-9352-162cfc0891be')
+        rules = self.driver.ex_list_firewall_rules(net)
+        specific_source_ip_rule = list(filter(lambda x: x.name == 'SpecificSourceIP',
+                                              rules))[0]
+        rule = self.driver.ex_create_firewall_rule(net, specific_source_ip_rule, 'FIRST')
+        self.assertEqual(rule.id, 'd0a20f59-77b9-4f28-a63b-e58496b73a6c')
+
+    def test_ex_create_firewall_rule_with_source_ip(self):
+        net = self.driver.ex_get_network_domain(
+            '8cdfd607-f429-4df6-9352-162cfc0891be')
+        rules = self.driver.ex_list_firewall_rules(net)
+        specific_source_ip_rule = \
+            list(filter(lambda x: x.name == 'SpecificSourceIP',
+                        rules))[0]
+        specific_source_ip_rule.source.any_ip = False
+        specific_source_ip_rule.source.ip_address = '10.0.0.1'
+        specific_source_ip_rule.source.ip_prefix_size = '15'
+        rule = self.driver.ex_create_firewall_rule(net,
+                                                   specific_source_ip_rule,
+                                                   'FIRST')
+        self.assertEqual(rule.id, 'd0a20f59-77b9-4f28-a63b-e58496b73a6c')
+
+    def test_ex_create_firewall_rule_with_any_ip(self):
+        net = self.driver.ex_get_network_domain(
+            '8cdfd607-f429-4df6-9352-162cfc0891be')
+        rules = self.driver.ex_list_firewall_rules(net)
+        specific_source_ip_rule = \
+            list(filter(lambda x: x.name == 'SpecificSourceIP',
+                        rules))[0]
+        specific_source_ip_rule.source.any_ip = True
+        rule = self.driver.ex_create_firewall_rule(net,
+                                                   specific_source_ip_rule,
+                                                   'FIRST')
+        self.assertEqual(rule.id, 'd0a20f59-77b9-4f28-a63b-e58496b73a6c')
+
+    def test_ex_create_firewall_rule_ip_prefix_size(self):
+        net = self.driver.ex_get_network_domain(
+            '8cdfd607-f429-4df6-9352-162cfc0891be')
+        rule = self.driver.ex_list_firewall_rules(net)[0]
+        rule.source.address_list_id = None
+        rule.source.any_ip = False
+        rule.source.ip_address = '10.2.1.1'
+        rule.source.ip_prefix_size = '10'
+        rule.destination.address_list_id = None
+        rule.destination.any_ip = False
+        rule.destination.ip_address = '10.0.0.1'
+        rule.destination.ip_prefix_size = '20'
+        self.driver.ex_create_firewall_rule(net, rule, 'LAST')
+
+    def test_ex_create_firewall_rule_address_list(self):
+        net = self.driver.ex_get_network_domain('8cdfd607-f429-4df6-9352-162cfc0891be')
+        rule = self.driver.ex_list_firewall_rules(net)[0]
+        rule.source.address_list_id = '12345'
+        rule.destination.address_list_id = '12345'
+        self.driver.ex_create_firewall_rule(net, rule, 'LAST')
+
+    def test_ex_create_firewall_rule_port_list(self):
+        net = self.driver.ex_get_network_domain('8cdfd607-f429-4df6-9352-162cfc0891be')
+        rule = self.driver.ex_list_firewall_rules(net)[0]
+        rule.source.port_list_id = '12345'
+        rule.destination.port_list_id = '12345'
+        self.driver.ex_create_firewall_rule(net, rule, 'LAST')
+
+    def test_ex_create_firewall_rule_port(self):
+        net = self.driver.ex_get_network_domain(
+            '8cdfd607-f429-4df6-9352-162cfc0891be')
+        rule = self.driver.ex_list_firewall_rules(net)[0]
+        rule.source.port_list_id = None
+        rule.source.port_begin = '8000'
+        rule.source.port_end = '8005'
+        rule.destination.port_list_id = None
+        rule.destination.port_begin = '7000'
+        rule.destination.port_end = '7005'
+        self.driver.ex_create_firewall_rule(net, rule, 'LAST')
+
+    def test_ex_create_firewall_rule_ALL_VALUES(self):
+        net = self.driver.ex_get_network_domain('8cdfd607-f429-4df6-9352-162cfc0891be')
+        rules = self.driver.ex_list_firewall_rules(net)
+        for rule in rules:
+            self.driver.ex_create_firewall_rule(net, rule, 'LAST')
+
+    def test_ex_create_firewall_rule_WITH_POSITION_RULE(self):
+        net = self.driver.ex_get_network_domain('8cdfd607-f429-4df6-9352-162cfc0891be')
+        rules = self.driver.ex_list_firewall_rules(net)
+        rule = self.driver.ex_create_firewall_rule(net, rules[-2], 'BEFORE', rules[-1])
+        self.assertEqual(rule.id, 'd0a20f59-77b9-4f28-a63b-e58496b73a6c')
+
+    def test_ex_create_firewall_rule_WITH_POSITION_RULE_STR(self):
+        net = self.driver.ex_get_network_domain('8cdfd607-f429-4df6-9352-162cfc0891be')
+        rules = self.driver.ex_list_firewall_rules(net)
+        rule = self.driver.ex_create_firewall_rule(net, rules[-2], 'BEFORE', 'RULE_WITH_SOURCE_AND_DEST')
+        self.assertEqual(rule.id, 'd0a20f59-77b9-4f28-a63b-e58496b73a6c')
+
+    def test_ex_create_firewall_rule_FAIL_POSITION(self):
+        net = self.driver.ex_get_network_domain('8cdfd607-f429-4df6-9352-162cfc0891be')
+        rules = self.driver.ex_list_firewall_rules(net)
+        with self.assertRaises(ValueError):
+            self.driver.ex_create_firewall_rule(net, rules[0], 'BEFORE')
+
+    def test_ex_create_firewall_rule_FAIL_POSITION_WITH_RULE(self):
+        net = self.driver.ex_get_network_domain('8cdfd607-f429-4df6-9352-162cfc0891be')
+        rules = self.driver.ex_list_firewall_rules(net)
+        with self.assertRaises(ValueError):
+            self.driver.ex_create_firewall_rule(net, rules[0], 'LAST', 'RULE_WITH_SOURCE_AND_DEST')
+
+    def test_ex_get_firewall_rule(self):
+        net = self.driver.ex_get_network_domain('8cdfd607-f429-4df6-9352-162cfc0891be')
+        rule = self.driver.ex_get_firewall_rule(net, 'd0a20f59-77b9-4f28-a63b-e58496b73a6c')
+        self.assertEqual(rule.id, 'd0a20f59-77b9-4f28-a63b-e58496b73a6c')
+
+    def test_ex_set_firewall_rule_state(self):
+        net = self.driver.ex_get_network_domain('8cdfd607-f429-4df6-9352-162cfc0891be')
+        rule = self.driver.ex_get_firewall_rule(net, 'd0a20f59-77b9-4f28-a63b-e58496b73a6c')
+        result = self.driver.ex_set_firewall_rule_state(rule, False)
+        self.assertTrue(result)
+
+    def test_ex_delete_firewall_rule(self):
+        net = self.driver.ex_get_network_domain('8cdfd607-f429-4df6-9352-162cfc0891be')
+        rule = self.driver.ex_get_firewall_rule(net, 'd0a20f59-77b9-4f28-a63b-e58496b73a6c')
+        result = self.driver.ex_delete_firewall_rule(rule)
+        self.assertTrue(result)
+
+    def test_ex_edit_firewall_rule(self):
+        net = self.driver.ex_get_network_domain(
+            '8cdfd607-f429-4df6-9352-162cfc0891be')
+        rule = self.driver.ex_get_firewall_rule(
+            net, 'd0a20f59-77b9-4f28-a63b-e58496b73a6c')
+        rule.source.any_ip = True
+        result = self.driver.ex_edit_firewall_rule(rule=rule, position='LAST')
+        self.assertTrue(result)
+
+    def test_ex_edit_firewall_rule_source_ipaddresslist(self):
+        net = self.driver.ex_get_network_domain(
+            '8cdfd607-f429-4df6-9352-162cfc0891be')
+        rule = self.driver.ex_get_firewall_rule(
+            net, 'd0a20f59-77b9-4f28-a63b-e58496b73a6c')
+        rule.source.address_list_id = '802abc9f-45a7-4efb-9d5a-810082368222'
+        rule.source.any_ip = False
+        rule.source.ip_address = '10.0.0.1'
+        rule.source.ip_prefix_size = 10
+        result = self.driver.ex_edit_firewall_rule(rule=rule, position='LAST')
+        self.assertTrue(result)
+
+    def test_ex_edit_firewall_rule_destination_ipaddresslist(self):
+        net = self.driver.ex_get_network_domain(
+            '8cdfd607-f429-4df6-9352-162cfc0891be')
+        rule = self.driver.ex_get_firewall_rule(
+            net, 'd0a20f59-77b9-4f28-a63b-e58496b73a6c')
+        rule.destination.address_list_id = '802abc9f-45a7-4efb-9d5a-810082368222'
+        rule.destination.any_ip = False
+        rule.destination.ip_address = '10.0.0.1'
+        rule.destination.ip_prefix_size = 10
+        result = self.driver.ex_edit_firewall_rule(rule=rule, position='LAST')
+        self.assertTrue(result)
+
+    def test_ex_edit_firewall_rule_destination_ipaddress(self):
+        net = self.driver.ex_get_network_domain(
+            '8cdfd607-f429-4df6-9352-162cfc0891be')
+        rule = self.driver.ex_get_firewall_rule(
+            net, 'd0a20f59-77b9-4f28-a63b-e58496b73a6c')
+        rule.source.address_list_id = None
+        rule.source.any_ip = False
+        rule.source.ip_address = '10.0.0.1'
+        rule.source.ip_prefix_size = '10'
+        result = self.driver.ex_edit_firewall_rule(rule=rule, position='LAST')
+        self.assertTrue(result)
+
+    def test_ex_edit_firewall_rule_source_ipaddress(self):
+        net = self.driver.ex_get_network_domain(
+            '8cdfd607-f429-4df6-9352-162cfc0891be')
+        rule = self.driver.ex_get_firewall_rule(
+            net, 'd0a20f59-77b9-4f28-a63b-e58496b73a6c')
+        rule.destination.address_list_id = None
+        rule.destination.any_ip = False
+        rule.destination.ip_address = '10.0.0.1'
+        rule.destination.ip_prefix_size = '10'
+        result = self.driver.ex_edit_firewall_rule(rule=rule, position='LAST')
+        self.assertTrue(result)
+
+    def test_ex_edit_firewall_rule_with_relative_rule(self):
+        net = self.driver.ex_get_network_domain(
+            '8cdfd607-f429-4df6-9352-162cfc0891be')
+        rule = self.driver.ex_get_firewall_rule(
+            net, 'd0a20f59-77b9-4f28-a63b-e58496b73a6c')
+        placement_rule = self.driver.ex_list_firewall_rules(
+            network_domain=net)[-1]
+        result = self.driver.ex_edit_firewall_rule(
+            rule=rule, position='BEFORE',
+            relative_rule_for_position=placement_rule)
+        self.assertTrue(result)
+
+    def test_ex_edit_firewall_rule_with_relative_rule_by_name(self):
+        net = self.driver.ex_get_network_domain(
+            '8cdfd607-f429-4df6-9352-162cfc0891be')
+        rule = self.driver.ex_get_firewall_rule(
+            net, 'd0a20f59-77b9-4f28-a63b-e58496b73a6c')
+        placement_rule = self.driver.ex_list_firewall_rules(
+            network_domain=net)[-1]
+        result = self.driver.ex_edit_firewall_rule(
+            rule=rule, position='BEFORE',
+            relative_rule_for_position=placement_rule.name)
+        self.assertTrue(result)
+
+    def test_ex_edit_firewall_rule_source_portlist(self):
+        net = self.driver.ex_get_network_domain(
+            '8cdfd607-f429-4df6-9352-162cfc0891be')
+        rule = self.driver.ex_get_firewall_rule(
+            net, 'd0a20f59-77b9-4f28-a63b-e58496b73a6c')
+        rule.source.port_list_id = '802abc9f-45a7-4efb-9d5a-810082368222'
+        result = self.driver.ex_edit_firewall_rule(rule=rule, position='LAST')
+        self.assertTrue(result)
+
+    def test_ex_edit_firewall_rule_source_port(self):
+        net = self.driver.ex_get_network_domain(
+            '8cdfd607-f429-4df6-9352-162cfc0891be')
+        rule = self.driver.ex_get_firewall_rule(
+            net, 'd0a20f59-77b9-4f28-a63b-e58496b73a6c')
+        rule.source.port_list_id = None
+        rule.source.port_begin = '3'
+        rule.source.port_end = '10'
+        result = self.driver.ex_edit_firewall_rule(rule=rule, position='LAST')
+        self.assertTrue(result)
+
+    def test_ex_edit_firewall_rule_destination_portlist(self):
+        net = self.driver.ex_get_network_domain(
+            '8cdfd607-f429-4df6-9352-162cfc0891be')
+        rule = self.driver.ex_get_firewall_rule(
+            net, 'd0a20f59-77b9-4f28-a63b-e58496b73a6c')
+        rule.destination.port_list_id = '802abc9f-45a7-4efb-9d5a-810082368222'
+        result = self.driver.ex_edit_firewall_rule(rule=rule, position='LAST')
+        self.assertTrue(result)
+
+    def test_ex_edit_firewall_rule_destination_port(self):
+        net = self.driver.ex_get_network_domain(
+            '8cdfd607-f429-4df6-9352-162cfc0891be')
+        rule = self.driver.ex_get_firewall_rule(
+            net, 'd0a20f59-77b9-4f28-a63b-e58496b73a6c')
+        rule.destination.port_list_id = None
+        rule.destination.port_begin = '3'
+        rule.destination.port_end = '10'
+        result = self.driver.ex_edit_firewall_rule(rule=rule, position='LAST')
+        self.assertTrue(result)
+
+    def test_ex_edit_firewall_rule_invalid_position_fail(self):
+        net = self.driver.ex_get_network_domain(
+            '8cdfd607-f429-4df6-9352-162cfc0891be')
+        rule = self.driver.ex_get_firewall_rule(
+            net, 'd0a20f59-77b9-4f28-a63b-e58496b73a6c')
+        with self.assertRaises(ValueError):
+            self.driver.ex_edit_firewall_rule(rule=rule, position='BEFORE')
+
+    def test_ex_edit_firewall_rule_invalid_position_relative_rule_fail(self):
+        net = self.driver.ex_get_network_domain(
+            '8cdfd607-f429-4df6-9352-162cfc0891be')
+        rule = self.driver.ex_get_firewall_rule(
+            net, 'd0a20f59-77b9-4f28-a63b-e58496b73a6c')
+        relative_rule = self.driver.ex_list_firewall_rules(
+            network_domain=net)[-1]
+        with self.assertRaises(ValueError):
+            self.driver.ex_edit_firewall_rule(rule=rule, position='FIRST',
+                                              relative_rule_for_position=relative_rule)
+
+    def test_ex_create_nat_rule(self):
+        net = self.driver.ex_get_network_domain('8cdfd607-f429-4df6-9352-162cfc0891be')
+        rule = self.driver.ex_create_nat_rule(net, '1.2.3.4', '4.3.2.1')
+        self.assertEqual(rule.id, 'd31c2db0-be6b-4d50-8744-9a7a534b5fba')
+
+    def test_ex_list_nat_rules(self):
+        net = self.driver.ex_get_network_domain('8cdfd607-f429-4df6-9352-162cfc0891be')
+        rules = self.driver.ex_list_nat_rules(net)
+        self.assertEqual(rules[0].id, '2187a636-7ebb-49a1-a2ff-5d617f496dce')
+        self.assertEqual(rules[0].internal_ip, '10.0.0.15')
+        self.assertEqual(rules[0].external_ip, '165.180.12.18')
+
+    def test_ex_get_nat_rule(self):
+        net = self.driver.ex_get_network_domain('8cdfd607-f429-4df6-9352-162cfc0891be')
+        rule = self.driver.ex_get_nat_rule(net, '2187a636-7ebb-49a1-a2ff-5d617f496dce')
+        self.assertEqual(rule.id, '2187a636-7ebb-49a1-a2ff-5d617f496dce')
+        self.assertEqual(rule.internal_ip, '10.0.0.16')
+        self.assertEqual(rule.external_ip, '165.180.12.19')
+
+    def test_ex_delete_nat_rule(self):
+        net = self.driver.ex_get_network_domain('8cdfd607-f429-4df6-9352-162cfc0891be')
+        rule = self.driver.ex_get_nat_rule(net, '2187a636-7ebb-49a1-a2ff-5d617f496dce')
+        result = self.driver.ex_delete_nat_rule(rule)
+        self.assertTrue(result)
+
+    def test_ex_enable_monitoring(self):
+        node = self.driver.list_nodes()[0]
+        result = self.driver.ex_enable_monitoring(node, "ADVANCED")
+        self.assertTrue(result)
+
+    def test_ex_disable_monitoring(self):
+        node = self.driver.list_nodes()[0]
+        result = self.driver.ex_disable_monitoring(node)
+        self.assertTrue(result)
+
+    def test_ex_change_monitoring_plan(self):
+        node = self.driver.list_nodes()[0]
+        result = self.driver.ex_update_monitoring_plan(node, "ESSENTIALS")
+        self.assertTrue(result)
+
+    def test_ex_add_storage_to_node(self):
+        node = self.driver.list_nodes()[0]
+        result = self.driver.ex_add_storage_to_node(node, 30, 'PERFORMANCE')
+        self.assertTrue(result)
+
+    def test_ex_remove_storage_from_node(self):
+        node = self.driver.list_nodes()[0]
+        result = self.driver.ex_remove_storage_from_node(node, 0)
+        self.assertTrue(result)
+
+    def test_ex_change_storage_speed(self):
+        node = self.driver.list_nodes()[0]
+        result = self.driver.ex_change_storage_speed(node, 1, 'PERFORMANCE')
+        self.assertTrue(result)
+
+    def test_ex_change_storage_size(self):
+        node = self.driver.list_nodes()[0]
+        result = self.driver.ex_change_storage_size(node, 1, 100)
+        self.assertTrue(result)
+
+    def test_ex_clone_node_to_image(self):
+        node = self.driver.list_nodes()[0]
+        result = self.driver.ex_clone_node_to_image(node, 'my image', 'a description')
+        self.assertTrue(result)
+
+    def test_ex_update_node(self):
+        node = self.driver.list_nodes()[0]
+        result = self.driver.ex_update_node(node, 'my new name', 'a description', 2, 4048)
+        self.assertTrue(result)
+
+    def test_ex_reconfigure_node(self):
+        node = self.driver.list_nodes()[0]
+        result = self.driver.ex_reconfigure_node(node, 4, 4, 1, 'HIGHPERFORMANCE')
+        self.assertTrue(result)
+
+    def test_ex_get_location_by_id(self):
+        location = self.driver.ex_get_location_by_id('NA9')
+        self.assertTrue(location.id, 'NA9')
+
+    def test_ex_get_location_by_id_NO_LOCATION(self):
+        location = self.driver.ex_get_location_by_id(None)
+        self.assertIsNone(location)
+
+    def test_ex_get_base_image_by_id(self):
+        image_id = self.driver.list_images()[0].id
+        image = self.driver.ex_get_base_image_by_id(image_id)
+        self.assertEqual(image.extra['OS_type'], 'UNIX')
+
+    def test_ex_get_customer_image_by_id(self):
+        image_id = self.driver.ex_list_customer_images()[1].id
+        image = self.driver.ex_get_customer_image_by_id(image_id)
+        self.assertEqual(image.extra['OS_type'], 'WINDOWS')
+
+    def test_ex_get_image_by_id_base_img(self):
+        image_id = self.driver.list_images()[1].id
+        image = self.driver.ex_get_base_image_by_id(image_id)
+        self.assertEqual(image.extra['OS_type'], 'WINDOWS')
+
+    def test_ex_get_image_by_id_customer_img(self):
+        image_id = self.driver.ex_list_customer_images()[0].id
+        image = self.driver.ex_get_customer_image_by_id(image_id)
+        self.assertEqual(image.extra['OS_type'], 'UNIX')
+
+    def test_ex_get_image_by_id_customer_FAIL(self):
+        image_id = 'FAKE_IMAGE_ID'
+        with self.assertRaises(DimensionDataAPIException):
+            self.driver.ex_get_base_image_by_id(image_id)
+
+    def test_ex_create_anti_affinity_rule(self):
+        node_list = self.driver.list_nodes()
+        success = self.driver.ex_create_anti_affinity_rule([node_list[0], node_list[1]])
+        self.assertTrue(success)
+
+    def test_ex_create_anti_affinity_rule_TUPLE(self):
+        node_list = self.driver.list_nodes()
+        success = self.driver.ex_create_anti_affinity_rule((node_list[0], node_list[1]))
+        self.assertTrue(success)
+
+    def test_ex_create_anti_affinity_rule_TUPLE_STR(self):
+        node_list = self.driver.list_nodes()
+        success = self.driver.ex_create_anti_affinity_rule((node_list[0].id, node_list[1].id))
+        self.assertTrue(success)
+
+    def test_ex_create_anti_affinity_rule_FAIL_STR(self):
+        node_list = 'string'
+        with self.assertRaises(TypeError):
+            self.driver.ex_create_anti_affinity_rule(node_list)
+
+    def test_ex_create_anti_affinity_rule_FAIL_EXISTING(self):
+        node_list = self.driver.list_nodes()
+        DimensionDataMockHttp.type = 'FAIL_EXISTING'
+        with self.assertRaises(DimensionDataAPIException):
+            self.driver.ex_create_anti_affinity_rule((node_list[0], node_list[1]))
+
+    def test_ex_delete_anti_affinity_rule(self):
+        net_domain = self.driver.ex_list_network_domains()[0]
+        rule = self.driver.ex_list_anti_affinity_rules(network_domain=net_domain)[0]
+        success = self.driver.ex_delete_anti_affinity_rule(rule)
+        self.assertTrue(success)
+
+    def test_ex_delete_anti_affinity_rule_STR(self):
+        net_domain = self.driver.ex_list_network_domains()[0]
+        rule = self.driver.ex_list_anti_affinity_rules(network_domain=net_domain)[0]
+        success = self.driver.ex_delete_anti_affinity_rule(rule.id)
+        self.assertTrue(success)
+
+    def test_ex_delete_anti_affinity_rule_FAIL(self):
+        net_domain = self.driver.ex_list_network_domains()[0]
+        rule = self.driver.ex_list_anti_affinity_rules(network_domain=net_domain)[0]
+        DimensionDataMockHttp.type = 'FAIL'
+        with self.assertRaises(DimensionDataAPIException):
+            self.driver.ex_delete_anti_affinity_rule(rule)
+
+    def test_ex_list_anti_affinity_rules_NETWORK_DOMAIN(self):
+        net_domain = self.driver.ex_list_network_domains()[0]
+        rules = self.driver.ex_list_anti_affinity_rules(network_domain=net_domain)
+        self.assertTrue(isinstance(rules, list))
+        self.assertEqual(len(rules), 2)
+        self.assertTrue(isinstance(rules[0].id, str))
+        self.assertTrue(isinstance(rules[0].node_list, list))
+
+    def test_ex_list_anti_affinity_rules_NETWORK(self):
+        network = self.driver.list_networks()[0]
+        rules = self.driver.ex_list_anti_affinity_rules(network=network)
+        self.assertTrue(isinstance(rules, list))
+        self.assertEqual(len(rules), 2)
+        self.assertTrue(isinstance(rules[0].id, str))
+        self.assertTrue(isinstance(rules[0].node_list, list))
+
+    def test_ex_list_anti_affinity_rules_NODE(self):
+        node = self.driver.list_nodes()[0]
+        rules = self.driver.ex_list_anti_affinity_rules(node=node)
+        self.assertTrue(isinstance(rules, list))
+        self.assertEqual(len(rules), 2)
+        self.assertTrue(isinstance(rules[0].id, str))
+        self.assertTrue(isinstance(rules[0].node_list, list))
+
+    def test_ex_list_anti_affinity_rules_PAGINATED(self):
+        net_domain = self.driver.ex_list_network_domains()[0]
+        DimensionDataMockHttp.type = 'PAGINATED'
+        rules = self.driver.ex_list_anti_affinity_rules(network_domain=net_domain)
+        self.assertTrue(isinstance(rules, list))
+        self.assertEqual(len(rules), 4)
+        self.assertTrue(isinstance(rules[0].id, str))
+        self.assertTrue(isinstance(rules[0].node_list, list))
+
+    def test_ex_list_anti_affinity_rules_ALLFILTERS(self):
+        net_domain = self.driver.ex_list_network_domains()[0]
+        DimensionDataMockHttp.type = 'ALLFILTERS'
+        rules = self.driver.ex_list_anti_affinity_rules(network_domain=net_domain, filter_id='FAKE_ID', filter_state='FAKE_STATE')
+        self.assertTrue(isinstance(rules, list))
+        self.assertEqual(len(rules), 2)
+        self.assertTrue(isinstance(rules[0].id, str))
+        self.assertTrue(isinstance(rules[0].node_list, list))
+
+    def test_ex_list_anti_affinity_rules_BAD_ARGS(self):
+        with self.assertRaises(ValueError):
+            self.driver.ex_list_anti_affinity_rules(network='fake_network', network_domain='fake_network_domain')
+
+    def test_ex_create_tag_key(self):
+        success = self.driver.ex_create_tag_key('MyTestKey')
+        self.assertTrue(success)
+
+    def test_ex_create_tag_key_ALLPARAMS(self):
+        self.driver.connection._get_orgId()
+        DimensionDataMockHttp.type = 'ALLPARAMS'
+        success = self.driver.ex_create_tag_key('MyTestKey', description="Test Key Desc.", value_required=False, display_on_report=False)
+        self.assertTrue(success)
+
+    def test_ex_create_tag_key_BADREQUEST(self):
+        self.driver.connection._get_orgId()
+        DimensionDataMockHttp.type = 'BADREQUEST'
+        with self.assertRaises(DimensionDataAPIException):
+            self.driver.ex_create_tag_key('MyTestKey')
+
+    def test_ex_list_tag_keys(self):
+        tag_keys = self.driver.ex_list_tag_keys()
+        self.assertTrue(isinstance(tag_keys, list))
+        self.assertTrue(isinstance(tag_keys[0], DimensionDataTagKey))
+        self.assertTrue(isinstance(tag_keys[0].id, str))
+
+    def test_ex_list_tag_keys_ALLFILTERS(self):
+        self.driver.connection._get_orgId()
+        DimensionDataMockHttp.type = 'ALLFILTERS'
+        self.driver.ex_list_tag_keys(id='fake_id', name='fake_name', value_required=False, display_on_report=False)
+
+    def test_ex_get_tag_by_id(self):
+        tag = self.driver.ex_get_tag_key_by_id('d047c609-93d7-4bc5-8fc9-732c85840075')
+        self.assertTrue(isinstance(tag, DimensionDataTagKey))
+
+    def test_ex_get_tag_by_id_NOEXIST(self):
+        self.driver.connection._get_orgId()
+        DimensionDataMockHttp.type = 'NOEXIST'
+        with self.assertRaises(DimensionDataAPIException):
+            self.driver.ex_get_tag_key_by_id('d047c609-93d7-4bc5-8fc9-732c85840075')
+
+    def test_ex_get_tag_by_name(self):
+        self.driver.connection._get_orgId()
+        DimensionDataMockHttp.type = 'SINGLE'
+        tag = self.driver.ex_get_tag_key_by_name('LibcloudTest')
+        self.assertTrue(isinstance(tag, DimensionDataTagKey))
+
+    def test_ex_get_tag_by_name_NOEXIST(self):
+        with self.assertRaises(ValueError):
+            self.driver.ex_get_tag_key_by_name('LibcloudTest')
+
+    def test_ex_modify_tag_key_NAME(self):
+        tag_key = self.driver.ex_list_tag_keys()[0]
+        DimensionDataMockHttp.type = 'NAME'
+        success = self.driver.ex_modify_tag_key(tag_key, name='NewName')
+        self.assertTrue(success)
+
+    def test_ex_modify_tag_key_NOTNAME(self):
+        tag_key = self.driver.ex_list_tag_keys()[0]
+        DimensionDataMockHttp.type = 'NOTNAME'
+        success = self.driver.ex_modify_tag_key(tag_key, description='NewDesc', value_required=False, display_on_report=True)
+        self.assertTrue(success)
+
+    def test_ex_modify_tag_key_NOCHANGE(self):
+        tag_key = self.driver.ex_list_tag_keys()[0]
+        DimensionDataMockHttp.type = 'NOCHANGE'
+        with self.assertRaises(DimensionDataAPIException):
+            self.driver.ex_modify_tag_key(tag_key)
+
+    def test_ex_remove_tag_key(self):
+        tag_key = self.driver.ex_list_tag_keys()[0]
+        success = self.driver.ex_remove_tag_key(tag_key)
+        self.assertTrue(success)
+
+    def test_ex_remove_tag_key_NOEXIST(self):
+        tag_key = self.driver.ex_list_tag_keys()[0]
+        DimensionDataMockHttp.type = 'NOEXIST'
+        with self.assertRaises(DimensionDataAPIException):
+            self.driver.ex_remove_tag_key(tag_key)
+
+    def test_ex_apply_tag_to_asset(self):
+        node = self.driver.list_nodes()[0]
+        success = self.driver.ex_apply_tag_to_asset(node, 'TagKeyName', 'FakeValue')
+        self.assertTrue(success)
+
+    def test_ex_apply_tag_to_asset_NOVALUE(self):
+        node = self.driver.list_nodes()[0]
+        DimensionDataMockHttp.type = 'NOVALUE'
+        success = self.driver.ex_apply_tag_to_asset(node, 'TagKeyName')
+        self.assertTrue(success)
+
+    def test_ex_apply_tag_to_asset_NOTAGKEY(self):
+        node = self.driver.list_nodes()[0]
+        DimensionDataMockHttp.type = 'NOTAGKEY'
+        with self.assertRaises(DimensionDataAPIException):
+            self.driver.ex_apply_tag_to_asset(node, 'TagKeyNam')
+
+    def test_ex_apply_tag_to_asset_BADASSETTYPE(self):
+        network = self.driver.list_networks()[0]
+        DimensionDataMockHttp.type = 'NOTAGKEY'
+        with self.assertRaises(TypeError):
+            self.driver.ex_apply_tag_to_asset(network, 'TagKeyNam')
+
+    def test_ex_remove_tag_from_asset(self):
+        node = self.driver.list_nodes()[0]
+        success = self.driver.ex_remove_tag_from_asset(node, 'TagKeyName')
+        self.assertTrue(success)
+
+    def test_ex_remove_tag_from_asset_NOTAG(self):
+        node = self.driver.list_nodes()[0]
+        DimensionDataMockHttp.type = 'NOTAG'
+        with self.assertRaises(DimensionDataAPIException):
+            self.driver.ex_remove_tag_from_asset(node, 'TagKeyNam')
+
+    def test_ex_list_tags(self):
+        tags = self.driver.ex_list_tags()
+        self.assertTrue(isinstance(tags, list))
+        self.assertTrue(isinstance(tags[0], DimensionDataTag))
+        self.assertTrue(len(tags) == 3)
+
+    def test_ex_list_tags_ALLPARAMS(self):
+        self.driver.connection._get_orgId()
+        DimensionDataMockHttp.type = 'ALLPARAMS'
+        tags = self.driver.ex_list_tags(asset_id='fake_asset_id', asset_type='fake_asset_type',
+                                        location='fake_location', tag_key_name='fake_tag_key_name',
+                                        tag_key_id='fake_tag_key_id', value='fake_value',
+                                        value_required=False, display_on_report=False)
+        self.assertTrue(isinstance(tags, list))
+        self.assertTrue(isinstance(tags[0], DimensionDataTag))
+        self.assertTrue(len(tags) == 3)
+
+    def test_priv_location_to_location_id(self):
+        location = self.driver.ex_get_location_by_id('NA9')
+        self.assertEqual(
+            self.driver._location_to_location_id(location),
+            'NA9'
+        )
+
+    def test_priv_location_to_location_id_STR(self):
+        self.assertEqual(
+            self.driver._location_to_location_id('NA9'),
+            'NA9'
+        )
+
+    def test_priv_location_to_location_id_TYPEERROR(self):
+        with self.assertRaises(TypeError):
+            self.driver._location_to_location_id([1, 2, 3])
+
+    def test_priv_image_needs_auth_os_img(self):
+        image = self.driver.list_images()[1]
+        self.assertTrue(self.driver._image_needs_auth(image))
+
+    def test_priv_image_needs_auth_os_img_STR(self):
+        image = self.driver.list_images()[1].id
+        self.assertTrue(self.driver._image_needs_auth(image))
+
+    def test_priv_image_needs_auth_cust_img_windows(self):
+        image = self.driver.ex_list_customer_images()[1]
+        self.assertTrue(self.driver._image_needs_auth(image))
+
+    def test_priv_image_needs_auth_cust_img_windows_STR(self):
+        image = self.driver.ex_list_customer_images()[1].id
+        self.assertTrue(self.driver._image_needs_auth(image))
+
+    def test_priv_image_needs_auth_cust_img_linux(self):
+        image = self.driver.ex_list_customer_images()[0]
+        self.assertTrue(not self.driver._image_needs_auth(image))
+
+    def test_priv_image_needs_auth_cust_img_linux_STR(self):
+        image = self.driver.ex_list_customer_images()[0].id
+        self.assertTrue(not self.driver._image_needs_auth(image))
+
+    def test_summary_usage_report(self):
+        report = self.driver.ex_summary_usage_report('2016-06-01', '2016-06-30')
+        report_content = report
+        self.assertEqual(len(report_content), 13)
+        self.assertEqual(len(report_content[0]), 6)
+
+    def test_detailed_usage_report(self):
+        report = self.driver.ex_detailed_usage_report('2016-06-01', '2016-06-30')
+        report_content = report
+        self.assertEqual(len(report_content), 42)
+        self.assertEqual(len(report_content[0]), 4)
+
+    def test_audit_log_report(self):
+        report = self.driver.ex_audit_log_report('2016-06-01', '2016-06-30')
+        report_content = report
+        self.assertEqual(len(report_content), 25)
+        self.assertEqual(report_content[2][2], 'OEC_SYSTEM')
+
+    def test_ex_list_ip_address_list(self):
+        net_domain = self.driver.ex_list_network_domains()[0]
+        ip_list = self.driver.ex_list_ip_address_list(
+            ex_network_domain=net_domain)
+        self.assertTrue(isinstance(ip_list, list))
+        self.assertEqual(len(ip_list), 4)
+        self.assertTrue(isinstance(ip_list[0].name, str))
+        self.assertTrue(isinstance(ip_list[0].description, str))
+        self.assertTrue(isinstance(ip_list[0].ip_version, str))
+        self.assertTrue(isinstance(ip_list[0].state, str))
+        self.assertTrue(isinstance(ip_list[0].create_time, str))
+        self.assertTrue(isinstance(ip_list[0].child_ip_address_lists, list))
+        self.assertEqual(len(ip_list[1].child_ip_address_lists), 1)
+        self.assertTrue(isinstance(ip_list[1].child_ip_address_lists[0].name,
+                                   str))
+
+    def test_ex_get_ip_address_list(self):
+        net_domain = self.driver.ex_list_network_domains()[0]
+        DimensionDataMockHttp.type = 'FILTERBYNAME'
+        ip_list = self.driver.ex_get_ip_address_list(
+            ex_network_domain=net_domain.id,
+            ex_ip_address_list_name='Test_IP_Address_List_3')
+        self.assertTrue(isinstance(ip_list, list))
+        self.assertEqual(len(ip_list), 1)
+        self.assertTrue(isinstance(ip_list[0].name, str))
+        self.assertTrue(isinstance(ip_list[0].description, str))
+        self.assertTrue(isinstance(ip_list[0].ip_version, str))
+        self.assertTrue(isinstance(ip_list[0].state, str))
+        self.assertTrue(isinstance(ip_list[0].create_time, str))
+        ips = ip_list[0].ip_address_collection
+        self.assertEqual(len(ips), 3)
+        self.assertTrue(isinstance(ips[0].begin, str))
+        self.assertTrue(isinstance(ips[0].prefix_size, str))
+        self.assertTrue(isinstance(ips[2].end, str))
+
+    def test_ex_create_ip_address_list_FAIL(self):
+        net_domain = self.driver.ex_list_network_domains()[0]
+
+        with self.assertRaises(TypeError):
+            self.driver.ex_create_ip_address_list(
+                ex_network_domain=net_domain.id)
+
+    def test_ex_create_ip_address_list(self):
+        name = "Test_IP_Address_List_3"
+        description = "Test Description"
+        ip_version = "IPV4"
+        child_ip_address_list_id = '0291ef78-4059-4bc1-b433-3f6ad698dc41'
+        child_ip_address_list = DimensionDataChildIpAddressList(
+            id=child_ip_address_list_id,
+            name="test_child_ip_addr_list")
+        net_domain = self.driver.ex_list_network_domains()[0]
+        ip_address_1 = DimensionDataIpAddress(begin='190.2.2.100')
+        ip_address_2 = DimensionDataIpAddress(begin='190.2.2.106',
+                                              end='190.2.2.108')
+        ip_address_3 = DimensionDataIpAddress(begin='190.2.2.0',
+                                              prefix_size='24')
+        ip_address_collection = [ip_address_1, ip_address_2,
+                                 ip_address_3]
+
+        # Create IP Address List
+        success = self.driver.ex_create_ip_address_list(
+            ex_network_domain=net_domain, name=name,
+            ip_version=ip_version, description=description,
+            ip_address_collection=ip_address_collection,
+            child_ip_address_list=child_ip_address_list)
+
+        self.assertTrue(success)
+
+    def test_ex_create_ip_address_list_STR(self):
+        name = "Test_IP_Address_List_3"
+        description = "Test Description"
+        ip_version = "IPV4"
+        child_ip_address_list_id = '0291ef78-4059-4bc1-b433-3f6ad698dc41'
+        net_domain = self.driver.ex_list_network_domains()[0]
+        ip_address_1 = DimensionDataIpAddress(begin='190.2.2.100')
+        ip_address_2 = DimensionDataIpAddress(begin='190.2.2.106',
+                                              end='190.2.2.108')
+        ip_address_3 = DimensionDataIpAddress(begin='190.2.2.0',
+                                              prefix_size='24')
+        ip_address_collection = [ip_address_1, ip_address_2,
+                                 ip_address_3]
+
+        # Create IP Address List
+        success = self.driver.ex_create_ip_address_list(
+            ex_network_domain=net_domain.id, name=name,
+            ip_version=ip_version, description=description,
+            ip_address_collection=ip_address_collection,
+            child_ip_address_list=child_ip_address_list_id)
+
+        self.assertTrue(success)
+
+    def test_ex_edit_ip_address_list(self):
+        ip_address_1 = DimensionDataIpAddress(begin='190.2.2.111')
+        ip_address_collection = [ip_address_1]
+
+        child_ip_address_list = DimensionDataChildIpAddressList(
+            id='2221ef78-4059-4bc1-b433-3f6ad698dc41',
+            name="test_child_ip_address_list edited")
+
+        ip_address_list = DimensionDataIpAddressList(
+            id='1111ef78-4059-4bc1-b433-3f6ad698d111',
+            name="test ip address list edited",
+            ip_version="IPv4", description="test",
+            ip_address_collection=ip_address_collection,
+            child_ip_address_lists=child_ip_address_list,
+            state="NORMAL",
+            create_time='2015-09-29T02:49:45'
+        )
+
+        success = self.driver.ex_edit_ip_address_list(
+            ex_ip_address_list=ip_address_list,
+            description="test ip address list",
+            ip_address_collection=ip_address_collection,
+            child_ip_address_lists=child_ip_address_list
+        )
+
+        self.assertTrue(success)
+
+    def test_ex_edit_ip_address_list_STR(self):
+        ip_address_1 = DimensionDataIpAddress(begin='190.2.2.111')
+        ip_address_collection = [ip_address_1]
+
+        child_ip_address_list = DimensionDataChildIpAddressList(
+            id='2221ef78-4059-4bc1-b433-3f6ad698dc41',
+            name="test_child_ip_address_list edited")
+
+        success = self.driver.ex_edit_ip_address_list(
+            ex_ip_address_list='84e34850-595d- 436e-a885-7cd37edb24a4',
+            description="test ip address list",
+            ip_address_collection=ip_address_collection,
+            child_ip_address_lists=child_ip_address_list
+        )
+
+        self.assertTrue(success)
+
+    def test_ex_delete_ip_address_list(self):
+        child_ip_address_list = DimensionDataChildIpAddressList(
+            id='2221ef78-4059-4bc1-b433-3f6ad698dc41',
+            name="test_child_ip_address_list edited")
+
+        ip_address_list = DimensionDataIpAddressList(
+            id='1111ef78-4059-4bc1-b433-3f6ad

<TRUNCATED>

[36/40] libcloud git commit: Remove unsupported qa env

Posted by an...@apache.org.
Remove unsupported qa env


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

Branch: refs/heads/trunk
Commit: 8db131a743ee4a8940bc8687ec6b20a505872fa3
Parents: b27bbe0
Author: Samuel Chong <sa...@gmail.com>
Authored: Fri Nov 25 14:58:36 2016 +1100
Committer: Samuel Chong <sa...@gmail.com>
Committed: Fri Nov 25 14:58:36 2016 +1100

----------------------------------------------------------------------
 libcloud/common/dimensiondata.py | 5 -----
 1 file changed, 5 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/libcloud/blob/8db131a7/libcloud/common/dimensiondata.py
----------------------------------------------------------------------
diff --git a/libcloud/common/dimensiondata.py b/libcloud/common/dimensiondata.py
index cf928c4..786a163 100644
--- a/libcloud/common/dimensiondata.py
+++ b/libcloud/common/dimensiondata.py
@@ -269,11 +269,6 @@ API_ENDPOINTS = {
         'name': 'Africa (AF)',
         'host': 'afapi.bsnlcloud.com',
         'vendor': 'BSNL'
-    },
-    'dd-qa': {
-        'name': 'Test(QA)',
-        'host': 'apiqa1geo1.itaas.dimensiondata.com',
-        'vendor': 'DimensionData'
     }
 }
 


[18/40] libcloud git commit: Unit tests for 2.3

Posted by an...@apache.org.
http://git-wip-us.apache.org/repos/asf/libcloud/blob/bb1b8104/libcloud/test/compute/fixtures/dimensiondata/2.4/image_osImage.xml
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/dimensiondata/2.4/image_osImage.xml b/libcloud/test/compute/fixtures/dimensiondata/2.4/image_osImage.xml
new file mode 100644
index 0000000..1f884a9
--- /dev/null
+++ b/libcloud/test/compute/fixtures/dimensiondata/2.4/image_osImage.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<osImages xmlns="urn:didata.com:api:cloud:types" pageNumber="1" pageCount="47" totalCount="47" pageSize="250">
+    <osImage id="c14b1a46-2428-44c1-9c1a-b20e6418d08c" datacenterId="NA9">
+        <name>RedHat 6 64-bit 2 CPU</name>
+        <description>RedHat 6.6 Enterprise (Santiago) 64-bit</description>
+        <operatingSystem id="REDHAT664" displayName="REDHAT6/64" family="UNIX" />
+        <cpu count="2" speed="STANDARD" coresPerSocket="1" />
+        <memoryGb>4</memoryGb>
+        <disk id="a02b7244-99d8-4889-84a5-5e4373c1bb26" scsiId="0" sizeGb="10" speed="STANDARD" />
+        <createTime>2015-09-17T11:23:48.000Z</createTime>
+        <osImageKey>T-RHEL-6-64-2-4-10</osImageKey>
+    </osImage>
+    <osImage id="6b4fb0c7-a57b-4f58-b59c-9958f94f971a" datacenterId="NA9">
+        <name>Win2012 DC 2 CPU</name>
+        <description>Windows 2012 Datacenter</description>
+        <operatingSystem id="WIN2012DC64" displayName="WIN2012DC/64" family="WINDOWS" />
+        <cpu count="2" speed="STANDARD" coresPerSocket="1" />
+        <memoryGb>4</memoryGb>
+        <disk id="f5e01854-a211-4ec6-96d6-2753b6d47877" scsiId="0" sizeGb="50" speed="STANDARD" />
+        <createTime>2015-09-17T11:44:43.000Z</createTime>
+        <osImageKey>T-WIN-2012-DATACTR-64-2-4-50</osImageKey>
+    </osImage>
+    <osImage id="3ebf3c0f-90fe-4a8b-8585-6e65b316592c" datacenterId="NA9">
+        <name>Win2008 Std 32-bit 2 CPU</name>
+        <description>Windows 2008 Enterprise R2 32-bit installed with Microsoft SQL Server 2012 Standard Edition</description>
+        <operatingSystem id="WIN2008S32" displayName="WIN2008S/32" family="WINDOWS" />
+        <cpu count="2" speed="STANDARD" coresPerSocket="1" />
+        <memoryGb>4</memoryGb>
+        <disk id="6e5b5112-0eae-44eb-83cd-1bd0d58fbeab" scsiId="0" sizeGb="50" speed="STANDARD" />
+        <softwareLabel>MSSQL2008R2S</softwareLabel>
+        <createTime>2014-11-20T12:54:22.000Z</createTime>
+        <osImageKey>T-WIN-2008-ENT-32-2-4-50</osImageKey>
+    </osImage>
+</osImages>

http://git-wip-us.apache.org/repos/asf/libcloud/blob/bb1b8104/libcloud/test/compute/fixtures/dimensiondata/2.4/image_osImage_6b4fb0c7_a57b_4f58_b59c_9958f94f971a.xml
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/dimensiondata/2.4/image_osImage_6b4fb0c7_a57b_4f58_b59c_9958f94f971a.xml b/libcloud/test/compute/fixtures/dimensiondata/2.4/image_osImage_6b4fb0c7_a57b_4f58_b59c_9958f94f971a.xml
new file mode 100644
index 0000000..1631137
--- /dev/null
+++ b/libcloud/test/compute/fixtures/dimensiondata/2.4/image_osImage_6b4fb0c7_a57b_4f58_b59c_9958f94f971a.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+  <osImage xmlns="urn:didata.com:api:cloud:types" id="6b4fb0c7-a57b-4f58-b59c-9958f94f971a" datacenterId="NA9">
+    <name>Win2012 DC 2 CPU</name>
+    <description>Windows 2012 Datacenter</description>
+    <operatingSystem id="WIN2012DC64" displayName="WIN2012DC/64" family="WINDOWS" />
+    <cpu count="2" speed="STANDARD" coresPerSocket="1" />
+    <memoryGb>4</memoryGb>
+    <disk id="f5e01854-a211-4ec6-96d6-2753b6d47877" scsiId="0" sizeGb="50" speed="STANDARD" />
+    <createTime>2015-09-17T11:44:43.000Z</createTime>
+    <osImageKey>T-WIN-2012-DATACTR-64-2-4-50</osImageKey>
+  </osImage>

http://git-wip-us.apache.org/repos/asf/libcloud/blob/bb1b8104/libcloud/test/compute/fixtures/dimensiondata/2.4/image_osImage_c14b1a46_2428_44c1_9c1a_b20e6418d08c.xml
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/dimensiondata/2.4/image_osImage_c14b1a46_2428_44c1_9c1a_b20e6418d08c.xml b/libcloud/test/compute/fixtures/dimensiondata/2.4/image_osImage_c14b1a46_2428_44c1_9c1a_b20e6418d08c.xml
new file mode 100644
index 0000000..27d6c25
--- /dev/null
+++ b/libcloud/test/compute/fixtures/dimensiondata/2.4/image_osImage_c14b1a46_2428_44c1_9c1a_b20e6418d08c.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+  <osImage xmlns="urn:didata.com:api:cloud:types" id="c14b1a46-2428-44c1-9c1a-b20e6418d08c" datacenterId="NA9">
+    <name>RedHat 6 64-bit 2 CPU</name>
+    <description>RedHat 6.6 Enterprise (Santiago) 64-bit</description>
+    <operatingSystem id="REDHAT664" displayName="REDHAT6/64" family="UNIX" />
+    <cpu count="2" speed="STANDARD" coresPerSocket="1" />
+    <memoryGb>4</memoryGb>
+    <disk id="a02b7244-99d8-4889-84a5-5e4373c1bb26" scsiId="0" sizeGb="10" speed="STANDARD" />
+    <createTime>2015-09-17T11:23:48.000Z</createTime>
+    <osImageKey>T-RHEL-6-64-2-4-10</osImageKey>
+  </osImage>
+

http://git-wip-us.apache.org/repos/asf/libcloud/blob/bb1b8104/libcloud/test/compute/fixtures/dimensiondata/image_customerImage.xml
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/dimensiondata/image_customerImage.xml b/libcloud/test/compute/fixtures/dimensiondata/image_customerImage.xml
deleted file mode 100644
index 0415d65..0000000
--- a/libcloud/test/compute/fixtures/dimensiondata/image_customerImage.xml
+++ /dev/null
@@ -1,59 +0,0 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<customerImages xmlns="urn:didata.com:api:cloud:types" pageNumber="1" pageCount="35" totalCount="35" pageSize="250">
-    <customerImage id="5234e5c7-01de-4411-8b6e-baeb8d91cf5d" datacenterId="NA9">
-        <name>ImportedCustomerImage</name>
-        <description />
-        <cpu count="4" speed="STANDARD" coresPerSocket="1" />
-        <memoryGb>2</memoryGb>
-        <disk id="1a82316f-23ed-4fe9-b6d8-6b92ac467423" scsiId="0" sizeGb="12" speed="STANDARD" />
-        <createTime>2015-11-19T14:29:02.000Z</createTime>
-        <source type="IMPORT">
-            <artifact type="MF" value="ImportedCustomerImage.mf" date="2015-1119T14:28:54.000Z" />
-            <artifact type="OVF" value="ImportedCustomerImage.ovf" date="2015-1119T14:28:05.000Z" />
-            <artifact type="VMDK" value="ImportedCustomerImage-disk1.vmdk" date="2015-11-19T12:22:31.000Z" />
-        </source>
-        <virtualHardware version="vmx-10" upToDate="true" />
-        <state>NORMAL</state>
-        <guest osCustomization="true">
-            <operatingSystem id="REDHAT664" displayName="REDHAT6/64" family="UNIX"/>
-            <vmTools type="vmx-08" versionStatus="NEED_UPGRADE" runningStatus="NOT_RUNNING" apiVersion="8389"/>
-        </guest>
-    </customerImage>
-    <customerImage id="2ffa36c8-1848-49eb-b4fa-9d908775f68c" datacenterId="NA9">
-        <name>CustomerImageWithPricedSoftwareLabels</name>
-        <description />
-        <cpu count="1" speed="STANDARD" coresPerSocket="1" />
-        <memoryGb>1</memoryGb>
-        <disk id="29455efc-51af-4b4d-91b3-d81ca0dff7d8" scsiId="0" sizeGb="50" speed="STANDARD" />
-        <softwareLabel>MSSQL2008R2S</softwareLabel>
-        <createTime>2015-11-03T15:25:34.000Z</createTime>
-        <source type="CLONE">
-            <artifact type="SERVER_ID" value="7c9c2551-269d-4274-a247126ba7c6215c" />
-        </source>
-        <state>NORMAL</state>
-        <virtualHardware version="vmx-08" upToDate="false" />
-        <guest osCustomization="true">
-            <operatingSystem id="WIN2008S32" displayName="WIN2008S/32" family="WINDOWS" />
-            <vmTools type="vmx-08" versionStatus="CURRENT"
-                     runningStatus="NOT_RUNNING" />
-        </guest>
-    </customerImage>
-    <customerImage id="1fc1844f-45d6-4364-b447-f7c7645b47de" datacenterId="NA9">
-        <name>CopiedCustomerImage</name>
-        <description />
-        <cpu count="1" speed="STANDARD" coresPerSocket="1" />
-        <memoryGb>2</memoryGb>
-        <disk id="42b20819-c161-4dec-aa94-73ec370a6e37" scsiId="0" sizeGb="10" speed="STANDARD" />
-        <createTime>2015-11-11T17:17:00.000Z</createTime>
-        <source type="COPY">
-            <artifact type="IMAGE_ID" value="0b8357b6-f156-4b27-b4fd-b81d09c15efc" />
-        </source>
-        <state>NORMAL</state>
-        <virtualHardware version="vmx-10" upToDate="true" />
-        <guest osCustomization="true">
-            <operatingSystem id="REDHAT664" displayName="REDHAT6/64" family="UNIX" />
-            <vmTools type="vmx-08" versionStatus="NEED_UPGRADE"
-                     runningStatus="NOT_RUNNING" apiVersion="9355" />
-        </guest>
-    </customerImage>
-</customerImages>

http://git-wip-us.apache.org/repos/asf/libcloud/blob/bb1b8104/libcloud/test/compute/fixtures/dimensiondata/image_customerImage_2ffa36c8_1848_49eb_b4fa_9d908775f68c.xml
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/dimensiondata/image_customerImage_2ffa36c8_1848_49eb_b4fa_9d908775f68c.xml b/libcloud/test/compute/fixtures/dimensiondata/image_customerImage_2ffa36c8_1848_49eb_b4fa_9d908775f68c.xml
deleted file mode 100644
index 20627e1..0000000
--- a/libcloud/test/compute/fixtures/dimensiondata/image_customerImage_2ffa36c8_1848_49eb_b4fa_9d908775f68c.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-    <customerImage xmlns="urn:didata.com:api:cloud:types"
-                   id="2ffa36c8-1848-49eb-b4fa-9d908775f68c" datacenterId="NA9">
-        <name>CustomerImageWithPricedSoftwareLabels</name>
-        <description />
-        <cpu count="1" speed="STANDARD" coresPerSocket="1" />
-        <memoryGb>1</memoryGb>
-        <disk id="29455efc-51af-4b4d-91b3-d81ca0dff7d8" scsiId="0" sizeGb="50" speed="STANDARD" />
-        <softwareLabel>MSSQL2008R2S</softwareLabel>
-        <createTime>2015-11-03T15:25:34.000Z</createTime>
-        <source type="CLONE">
-            <artifact type="SERVER_ID" value="7c9c2551-269d-4274-a247126ba7c6215c" />
-        </source>
-        <state>NORMAL</state>
-        <virtualHardware version="vmx-08" upToDate="false" />
-        <guest osCustomization="true">
-            <operatingSystem id="WIN2008S32" displayName="WIN2008S/32" family="WINDOWS" />
-            <vmTools type="vmx-08" versionStatus="CURRENT"
-                     runningStatus="NOT_RUNNING" />
-        </guest>
-    </customerImage>

http://git-wip-us.apache.org/repos/asf/libcloud/blob/bb1b8104/libcloud/test/compute/fixtures/dimensiondata/image_customerImage_5234e5c7_01de_4411_8b6e_baeb8d91cf5d.xml
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/dimensiondata/image_customerImage_5234e5c7_01de_4411_8b6e_baeb8d91cf5d.xml b/libcloud/test/compute/fixtures/dimensiondata/image_customerImage_5234e5c7_01de_4411_8b6e_baeb8d91cf5d.xml
deleted file mode 100644
index f8ba258..0000000
--- a/libcloud/test/compute/fixtures/dimensiondata/image_customerImage_5234e5c7_01de_4411_8b6e_baeb8d91cf5d.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<customerImage  xmlns="urn:didata.com:api:cloud:types"
-                id="5234e5c7-01de-4411-8b6e-baeb8d91cf5d" datacenterId="NA9">
-        <name>ImportedCustomerImage</name>
-        <description />
-        <cpu count="4" speed="STANDARD" coresPerSocket="1" />
-        <memoryGb>2</memoryGb>
-        <disk id="1a82316f-23ed-4fe9-b6d8-6b92ac467423" scsiId="0" sizeGb="12" speed="STANDARD" />
-        <createTime>2015-11-19T14:29:02.000Z</createTime>
-        <source type="IMPORT">
-            <artifact type="MF" value="ImportedCustomerImage.mf" date="2015-1119T14:28:54.000Z" />
-            <artifact type="OVF" value="ImportedCustomerImage.ovf" date="2015-1119T14:28:05.000Z" />
-            <artifact type="VMDK" value="ImportedCustomerImage-disk1.vmdk" date="2015-11-19T12:22:31.000Z" />
-        </source>
-        <virtualHardware version="vmx-10" upToDate="true" />
-        <state>NORMAL</state>
-        <guest osCustomization="true">
-            <operatingSystem id="REDHAT664" displayName="REDHAT6/64" family="UNIX"/>
-            <vmTools type="vmx-08" versionStatus="NEED_UPGRADE" runningStatus="NOT_RUNNING" apiVersion="8389"/>
-        </guest>
-</customerImage>

http://git-wip-us.apache.org/repos/asf/libcloud/blob/bb1b8104/libcloud/test/compute/fixtures/dimensiondata/image_osImage.xml
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/dimensiondata/image_osImage.xml b/libcloud/test/compute/fixtures/dimensiondata/image_osImage.xml
deleted file mode 100644
index 4af7e09..0000000
--- a/libcloud/test/compute/fixtures/dimensiondata/image_osImage.xml
+++ /dev/null
@@ -1,43 +0,0 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<osImages xmlns="urn:didata.com:api:cloud:types" pageNumber="1" pageCount="47" totalCount="47" pageSize="250">
-    <osImage id="c14b1a46-2428-44c1-9c1a-b20e6418d08c" datacenterId="NA9">
-        <name>RedHat 6 64-bit 2 CPU</name>
-        <description>RedHat 6.6 Enterprise (Santiago) 64-bit</description>
-        <cpu count="2" speed="STANDARD" coresPerSocket="1"/>
-        <memoryGb>4</memoryGb>
-        <disk id="5f709ffe-ae38-4d3b-8aeb-57cbc5036627" scsiId="0" sizeGb="10" speed="STANDARD"/>
-        <createTime>2015-09-23T10:17:28.000Z</createTime>
-        <osImageKey>T-RHEL-6-64-2-4-10</osImageKey>
-        <sortOrder>0</sortOrder>
-        <guest osCustomization="true">
-            <operatingSystem id="REDHAT664" displayName="REDHAT6/64" family="UNIX"/>
-        </guest>
-    </osImage>
-    <osImage id="6b4fb0c7-a57b-4f58-b59c-9958f94f971a" datacenterId="NA9">
-        <name>Win2012 DC 2 CPU</name>
-        <description>Windows 2012 Datacenter</description>
-        <cpu count="2" speed="STANDARD" coresPerSocket="1"/>
-        <memoryGb>4</memoryGb>
-        <disk id="b74a54e6-f90a-4619-a232-4b7522cf0055" scsiId="0" sizeGb="50" speed="STANDARD"/>
-        <createTime>2015-09-23T10:19:51.000Z</createTime>
-        <osImageKey>T-WIN-2012-DATACTR-64-2-4-50</osImageKey>
-        <sortOrder>0</sortOrder>
-        <guest osCustomization="true">
-            <operatingSystem id="WIN2012DC64" displayName="WIN2012DC/64" family="WINDOWS"/>
-        </guest>
-    </osImage>
-    <osImage id="3ebf3c0f-90fe-4a8b-8585-6e65b316592c" datacenterId="NA9">
-        <name>Win2008 Std 32-bit 2 CPU</name>
-        <description>Windows 2008 Enterprise R2 32-bit installed with Microsoft SQL Server 2012 Standard Edition</description>
-        <cluster id="QA1_N2_VMWARE_1-01" name="QA1_N2_VMWARE_1-01"/>
-        <cpu count="2" speed="STANDARD" coresPerSocket="1"/>
-        <memoryGb>4</memoryGb>
-        <disk id="3ee8ecd1-cae6-4bb3-81b2-1294b7763d24" scsiId="0" sizeGb="50" speed="STANDARD"/>
-        <createTime>2015-06-16T14:22:41.000Z</createTime>
-        <osImageKey>T-WIN-2008-ENT-32-2-4-50</osImageKey>
-        <sortOrder>0</sortOrder>
-        <guest osCustomization="true">
-            <operatingSystem id="WIN2008S32" displayName="WIN2008S/32" family="WINDOWS"/>
-        </guest>
-    </osImage>
-</osImages>

http://git-wip-us.apache.org/repos/asf/libcloud/blob/bb1b8104/libcloud/test/compute/fixtures/dimensiondata/image_osImage_6b4fb0c7_a57b_4f58_b59c_9958f94f971a.xml
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/dimensiondata/image_osImage_6b4fb0c7_a57b_4f58_b59c_9958f94f971a.xml b/libcloud/test/compute/fixtures/dimensiondata/image_osImage_6b4fb0c7_a57b_4f58_b59c_9958f94f971a.xml
deleted file mode 100644
index a2ea8cb..0000000
--- a/libcloud/test/compute/fixtures/dimensiondata/image_osImage_6b4fb0c7_a57b_4f58_b59c_9958f94f971a.xml
+++ /dev/null
@@ -1,14 +0,0 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<osImage xmlns="urn:didata.com:api:cloud:types" id="6b4fb0c7-a57b-4f58-b59c-9958f94f971a" datacenterId="NA9">
-    <name>Win2012 DC 2 CPU</name>
-    <description>Windows 2012 Datacenter</description>
-        <cpu count="2" speed="STANDARD" coresPerSocket="1"/>
-        <memoryGb>4</memoryGb>
-        <disk id="b74a54e6-f90a-4619-a232-4b7522cf0055" scsiId="0" sizeGb="50" speed="STANDARD"/>
-        <createTime>2015-09-23T10:19:51.000Z</createTime>
-        <osImageKey>T-WIN-2012-DATACTR-64-2-4-50</osImageKey>
-        <sortOrder>0</sortOrder>
-        <guest osCustomization="true">
-            <operatingSystem id="WIN2012DC64" displayName="WIN2012DC/64" family="WINDOWS"/>
-        </guest>
-</osImage>

http://git-wip-us.apache.org/repos/asf/libcloud/blob/bb1b8104/libcloud/test/compute/fixtures/dimensiondata/image_osImage_c14b1a46_2428_44c1_9c1a_b20e6418d08c.xml
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/dimensiondata/image_osImage_c14b1a46_2428_44c1_9c1a_b20e6418d08c.xml b/libcloud/test/compute/fixtures/dimensiondata/image_osImage_c14b1a46_2428_44c1_9c1a_b20e6418d08c.xml
deleted file mode 100644
index 62fa6b0..0000000
--- a/libcloud/test/compute/fixtures/dimensiondata/image_osImage_c14b1a46_2428_44c1_9c1a_b20e6418d08c.xml
+++ /dev/null
@@ -1,17 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<osImage xmlns="urn:didata.com:api:cloud:types"
-         id="c14b1a46-2428-44c1-9c1a-b20e6418d08c" datacenterId="NA9">
-    <name>RedHat 6 64-bit 2 CPU</name>
-    <description>RedHat 6.6 Enterprise (Santiago) 64-bit</description>
-    <cpu count="2" speed="STANDARD" coresPerSocket="1" />
-    <memoryGb>4</memoryGb>
-    <disk id="5f709ffe-ae38-4d3b-8aeb-57cbc5036627" scsiId="0" sizeGb="10"
-          speed="STANDARD" />
-    <createTime>2015-09-23T10:17:28.000Z</createTime>
-    <osImageKey>T-RHEL-6-64-2-4-10</osImageKey>
-    <sortOrder>0</sortOrder>
-    <guest osCustomization="true">
-        <operatingSystem id="REDHAT664" displayName="REDHAT6/64"
-                         family="UNIX" />
-    </guest>
-</osImage>
\ No newline at end of file


[05/40] libcloud git commit: update variable names

Posted by an...@apache.org.
update variable names


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

Branch: refs/heads/trunk
Commit: 75111a446e8323df607c17703bfb4303eb966dde
Parents: 45fea8d
Author: Samuel Chong <sa...@gmail.com>
Authored: Tue Nov 8 15:16:38 2016 +1100
Committer: Samuel Chong <sa...@gmail.com>
Committed: Tue Nov 8 15:16:38 2016 +1100

----------------------------------------------------------------------
 libcloud/common/dimensiondata.py | 39 +++++++++++++++++++++++++++++------
 1 file changed, 33 insertions(+), 6 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/libcloud/blob/75111a44/libcloud/common/dimensiondata.py
----------------------------------------------------------------------
diff --git a/libcloud/common/dimensiondata.py b/libcloud/common/dimensiondata.py
index 0a868b8..c58d5dd 100644
--- a/libcloud/common/dimensiondata.py
+++ b/libcloud/common/dimensiondata.py
@@ -372,8 +372,16 @@ class DimensionDataConnection(ConnectionUserAndKey):
 
     api_path_version_1 = '/oec'
     api_path_version_2 = '/caas'
-    api_version_1 = '0.9'
-    api_version_2 = '2.3'
+    api_version_1 = 0.9
+
+    # Earliest version supported
+    oldest_api_version = 2.2
+
+    # Latest version supported
+    latest_api_version = 2.3
+
+    # Default api version
+    active_api_version = 2.3
 
     _orgId = None
     responseCls = DimensionDataResponse
@@ -396,8 +404,27 @@ class DimensionDataConnection(ConnectionUserAndKey):
             self.host = conn_kwargs['region']['host']
 
         if api_version:
-            if api_version.startswith('2'):
-                self.api_version_2 = api_version
+            if float(api_version) < self.oldest_api_version:
+                msg = 'API Version specified is too old. No longer ' \
+                      'supported. Please upgrade to the latest version {}' \
+                    .format(self.active_api_version)
+
+                raise DimensionDataAPIException(code=None,
+                                                msg=msg,
+                                                driver=self.driver)
+            elif float(api_version) > self.latest_api_version:
+                msg = 'Unsupported API Version. The version specified is ' \
+                      'not release yet. Please use the latest supported ' \
+                      'version {}' \
+                    .format(self.active_api_version)
+
+                raise DimensionDataAPIException(code=None,
+                                                msg=msg,
+                                                driver=self.driver)
+
+            else:
+                # Overwrite default version using the version user specified
+                self.active_api_version = api_version
 
     def add_default_headers(self, headers):
         headers['Authorization'] = \
@@ -419,7 +446,7 @@ class DimensionDataConnection(ConnectionUserAndKey):
     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)
+                                  self.active_api_version, path, action)
 
         return super(DimensionDataConnection, self).request(
             action=action,
@@ -520,7 +547,7 @@ class DimensionDataConnection(ConnectionUserAndKey):
         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,
+        return ("%s/%s/%s" % (self.api_path_version_2, self.active_api_version,
                               self._get_orgId()))
 
     def wait_for_state(self, state, func, poll_interval=2, timeout=60, *args,


[31/40] libcloud git commit: Import image documentation and validation for choice of cluster and datacenter id

Posted by an...@apache.org.
Import image documentation and validation for choice of cluster and datacenter id


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

Branch: refs/heads/trunk
Commit: 31a0bdad45135703784e2dc9e73d1564bd6be9b0
Parents: 060954e
Author: Samuel Chong <sa...@gmail.com>
Authored: Thu Nov 24 16:39:04 2016 +1100
Committer: Samuel Chong <sa...@gmail.com>
Committed: Thu Nov 24 16:39:04 2016 +1100

----------------------------------------------------------------------
 libcloud/compute/drivers/dimensiondata.py       | 167 ++++++++++++-------
 .../test/compute/test_dimensiondata_v2_4.py     |  26 +++
 2 files changed, 130 insertions(+), 63 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/libcloud/blob/31a0bdad/libcloud/compute/drivers/dimensiondata.py
----------------------------------------------------------------------
diff --git a/libcloud/compute/drivers/dimensiondata.py b/libcloud/compute/drivers/dimensiondata.py
index eec32a6..1455588 100644
--- a/libcloud/compute/drivers/dimensiondata.py
+++ b/libcloud/compute/drivers/dimensiondata.py
@@ -869,6 +869,110 @@ class DimensionDataNodeDriver(NodeDriver):
             .request_with_orgId_api_1('networkWithLocation%s' % url_ext)
             .object)
 
+    def import_image(self, ovf_package_name, name,
+                     cluster_id=None, datacenter_id=None, description=None,
+                     is_guest_os_customization=None,
+                     tagkey_name_value_dictionaries=None):
+        """
+        Import image
+
+        :param ovf_package_name: Image OVF package name
+        :type  ovf_package_name: ``str``
+
+        :param name: Image name
+        :type  name: ``str``
+
+        :param cluster_id: Provide either cluster_id or datacenter_id
+        :type  cluster_id: ``str``
+
+        :param datacenter_id: Provide either cluster_id or datacenter_id
+        :type  datacenter_id: ``str``
+
+        :param description: Optional. Description of image
+        :type  description: ``str``
+
+        :param is_guest_os_customization: Optional. true for NGOC image
+        :type  is_guest_os_customization: ``bool``
+
+        :param tagkey_name_value_dictionaries: Optional tagkey name value dict
+        :type  tagkey_name_value_dictionaries: dictionaries
+
+        :return: Return true if successful
+        :rtype:  ``bool``
+        """
+
+        # Unsupported for version lower than 2.4
+        if LooseVersion(self.connection.active_api_version) < LooseVersion(
+                '2.4'):
+            raise Exception("import image is feature is NOT supported in  " \
+                            "api version earlier than 2.4")
+        elif cluster_id is None and datacenter_id is None:
+            raise ValueError("Either cluster_id or datacenter_id must be "
+                             "provided")
+        elif cluster_id is not None and datacenter_id is not None:
+            raise ValueError("Cannot accept both cluster_id and "
+                             "datacenter_id. Please provide either one")
+        else:
+            import_image_elem = ET.Element(
+                'urn:importImage',
+                {
+                    'xmlns:urn': TYPES_URN,
+                })
+
+            ET.SubElement(
+                import_image_elem,
+                'urn:ovfPackage'
+            ).text = ovf_package_name
+
+            ET.SubElement(
+                import_image_elem,
+                'urn:name'
+            ).text = name
+
+            if description is not None:
+                ET.SubElement(
+                    import_image_elem,
+                    'urn:description'
+                ).text = description
+
+            if cluster_id is not None:
+                ET.SubElement(
+                    import_image_elem,
+                    'urn:clusterId'
+                ).text = cluster_id
+            else:
+                ET.SubElement(
+                    import_image_elem,
+                    'urn:datacenterId'
+                ).text = datacenter_id
+
+            if is_guest_os_customization is not None:
+                ET.SubElement(
+                    import_image_elem,
+                    'urn:guestOsCustomization'
+                ).text = is_guest_os_customization
+
+            if len(tagkey_name_value_dictionaries) > 0:
+                for k, v in tagkey_name_value_dictionaries.items():
+                    print(k, v)
+                    tag_elem = ET.SubElement(
+                        import_image_elem,
+                        'urn:tag')
+                    ET.SubElement(tag_elem,
+                                  'urn:tagKeyName').text = k
+
+                    if v is not None:
+                        ET.SubElement(tag_elem,
+                                      'urn:value').text = v
+
+        response = self.connection.request_with_orgId_api_2(
+            'image/importImage',
+            method='POST',
+            data=ET.tostring(import_image_elem)).object
+
+        response_code = findtext(response, 'responseCode', TYPES_URN)
+        return response_code in ['IN_PROGRESS', 'OK']
+
     def ex_list_nodes_paginated(self, name=None, location=None,
                                 ipv6=None, ipv4=None, vlan=None,
                                 image=None, deployed=None, started=None,
@@ -3626,69 +3730,6 @@ class DimensionDataNodeDriver(NodeDriver):
         response_code = findtext(response, 'responseCode', TYPES_URN)
         return response_code in ['IN_PROGRESS', 'OK']
 
-    def import_image(self, ovf_package_name, name,
-                     cluster_id, description=None,
-                     is_guest_os_customization=None,
-                     tagkey_name_value_dictionaries=None):
-        # Unsupported for version lower than 2.4
-        if LooseVersion(self.connection.active_api_version) < LooseVersion(
-                '2.4'):
-            raise Exception("import image is feature is NOT supported in  " \
-                            "api version earlier than 2.4")
-        else:
-            import_image_elem = ET.Element(
-                'urn:importImage',
-                {
-                    'xmlns:urn': TYPES_URN,
-                })
-
-            ET.SubElement(
-                import_image_elem,
-                'urn:ovfPackage'
-            ).text = ovf_package_name
-
-            ET.SubElement(
-                import_image_elem,
-                'urn:name'
-            ).text = name
-
-            if description is not None:
-                ET.SubElement(
-                    import_image_elem,
-                    'urn:description'
-                ).text = description
-
-            ET.SubElement(
-                import_image_elem,
-                'urn:clusterId'
-            ).text = cluster_id
-
-            if is_guest_os_customization is not None:
-                ET.SubElement(
-                    import_image_elem,
-                    'urn:guestOsCustomization'
-                ).text = is_guest_os_customization
-
-            if len(tagkey_name_value_dictionaries) > 0:
-                for k, v in tagkey_name_value_dictionaries.items():
-                    print(k, v)
-                    tag_elem = ET.SubElement(
-                        import_image_elem,
-                        'urn:tag')
-                    ET.SubElement(tag_elem,
-                                  'urn:tagKeyName').text = k
-
-                    if v is not None:
-                        ET.SubElement(tag_elem,
-                                      'urn:value').text = v
-
-        response = self.connection.request_with_orgId_api_2(
-            'image/importImage',
-            method='POST',
-            data=ET.tostring(import_image_elem)).object
-
-        response_code = findtext(response, 'responseCode', TYPES_URN)
-        return response_code in ['IN_PROGRESS', 'OK']
 
     def ex_exchange_nic_vlans(self, nic_id_1, nic_id_2):
         """

http://git-wip-us.apache.org/repos/asf/libcloud/blob/31a0bdad/libcloud/test/compute/test_dimensiondata_v2_4.py
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/test_dimensiondata_v2_4.py b/libcloud/test/compute/test_dimensiondata_v2_4.py
index caef5a8..ad4b980 100644
--- a/libcloud/test/compute/test_dimensiondata_v2_4.py
+++ b/libcloud/test/compute/test_dimensiondata_v2_4.py
@@ -2039,6 +2039,32 @@ class DimensionData_v2_4_Tests(unittest.TestCase, TestCaseMixin):
             tagkey_name_value_dictionaries=tag_dictionaries)
         self.assertTrue(success)
 
+    def test_import_image_error_too_many_choice(self):
+        tag_dictionaries = {'tagkey1_name': 'dev test', 'tagkey2_name': None}
+
+        with self.assertRaises(ValueError):
+            success = self.driver.import_image(
+                ovf_package_name='aTestGocToNGoc2_export2.mf',
+                name='Libcloud NGOCImage_New 2',
+                description='test',
+                cluster_id='QA1_N2_VMWARE_1-01',
+                datacenter_id='QA1_N1_VMWARE_1',
+                is_guest_os_customization='false',
+                tagkey_name_value_dictionaries=tag_dictionaries)
+
+    def test_import_image_error_missing_choice(self):
+        tag_dictionaries = {'tagkey1_name': 'dev test', 'tagkey2_name': None}
+
+        with self.assertRaises(ValueError):
+            success = self.driver.import_image(
+                ovf_package_name='aTestGocToNGoc2_export2.mf',
+                name='Libcloud NGOCImage_New 2',
+                description='test',
+                cluster_id=None,
+                datacenter_id=None,
+                is_guest_os_customization='false',
+                tagkey_name_value_dictionaries=tag_dictionaries)
+
     def test_exchange_nic_vlans(self):
         success = self.driver.ex_exchange_nic_vlans(
                   nic_id_1='a4b4b42b-ccb5-416f-b052-ce7cb7fdff12',


[29/40] libcloud git commit: Attempt to workaround pylint issue on import disutils.version on travis CI

Posted by an...@apache.org.
Attempt to workaround pylint issue on import disutils.version on travis CI


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

Branch: refs/heads/trunk
Commit: d8cdb924d1886fafcdaf532a6e434f79fa86e4f4
Parents: d2486ec
Author: Samuel Chong <sa...@gmail.com>
Authored: Wed Nov 23 15:53:19 2016 +1100
Committer: Samuel Chong <sa...@gmail.com>
Committed: Wed Nov 23 15:53:19 2016 +1100

----------------------------------------------------------------------
 libcloud/common/dimensiondata.py | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/libcloud/blob/d8cdb924/libcloud/common/dimensiondata.py
----------------------------------------------------------------------
diff --git a/libcloud/common/dimensiondata.py b/libcloud/common/dimensiondata.py
index a665eed..0cb726f 100644
--- a/libcloud/common/dimensiondata.py
+++ b/libcloud/common/dimensiondata.py
@@ -18,11 +18,14 @@ Dimension Data Common Components
 from base64 import b64encode
 from time import sleep
 
-from distutils.version import LooseVersion  # pylint: disable-msg=E0611
+try:
+    from distutils.version import LooseVersion  # pylint: disable=import-error
+except ImportError:
+    pass
+
 from libcloud.utils.py3 import httplib
 from libcloud.utils.py3 import b
 from libcloud.common.base import ConnectionUserAndKey, XmlResponse, RawResponse
-from libcloud.common.types import LibcloudError, InvalidCredsError
 from libcloud.compute.base import Node
 from libcloud.utils.py3 import basestring
 from libcloud.utils.xml import findtext


[32/40] libcloud git commit: Merge branch 'enable_api_version' into ngoc_images Get changes for version compare

Posted by an...@apache.org.
Merge branch 'enable_api_version' into ngoc_images
Get changes for version compare


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

Branch: refs/heads/trunk
Commit: 4284c31a457bb52ae24bf19afea1f80533babe41
Parents: 31a0bda 13eee8a
Author: Samuel Chong <sa...@gmail.com>
Authored: Fri Nov 25 10:57:57 2016 +1100
Committer: Samuel Chong <sa...@gmail.com>
Committed: Fri Nov 25 10:57:57 2016 +1100

----------------------------------------------------------------------
 CHANGES.rst                                     |   46 +
 .../_supported_methods_block_storage.rst        |    6 +-
 .../_supported_methods_key_pair_management.rst  |    2 +-
 docs/compute/_supported_providers.rst           |    2 +-
 docs/compute/drivers/azure.rst                  |   14 +-
 docs/compute/drivers/azure_arm.rst              |   54 +
 docs/compute/drivers/ec2.rst                    |    1 +
 docs/container/_supported_methods.rst           |    2 +-
 docs/examples/compute/azure_arm/instantiate.py  |    7 +
 docs/loadbalancer/_supported_methods.rst        |    2 +
 docs/loadbalancer/_supported_providers.rst      |    2 +
 docs/other/hacktoberfest.txt                    |    9 +-
 docs/storage/_supported_methods_cdn.rst         |    2 +
 docs/storage/_supported_methods_main.rst        |    2 +
 docs/storage/_supported_providers.rst           |    2 +
 libcloud/__init__.py                            |    2 +-
 libcloud/common/azure.py                        |    2 +
 libcloud/common/azure_arm.py                    |  124 +
 libcloud/common/base.py                         |   19 +-
 libcloud/common/cloudsigma.py                   |    5 +
 libcloud/common/dimensiondata.py                |   11 +-
 libcloud/common/google.py                       |    4 +-
 libcloud/compute/drivers/azure_arm.py           | 1281 +++++
 libcloud/compute/drivers/ec2.py                 |   65 +-
 libcloud/compute/drivers/ecs.py                 |   27 +-
 libcloud/compute/drivers/gce.py                 |   20 +-
 libcloud/compute/drivers/profitbricks.py        | 4101 ++++++++++---
 libcloud/compute/providers.py                   |    2 +
 libcloud/compute/types.py                       |    7 +-
 libcloud/loadbalancer/drivers/alb.py            |  321 ++
 libcloud/loadbalancer/providers.py              |    2 +
 libcloud/loadbalancer/types.py                  |    1 +
 libcloud/storage/drivers/s3.py                  |   12 +
 libcloud/storage/providers.py                   |    2 +
 libcloud/storage/types.py                       |    2 +
 libcloud/test/common/test_google.py             |   13 +-
 ...777_7777_7777_777777777777_oauth2_token.json |    1 +
 ...99999999999_providers_Microsoft_Compute.json |  200 +
 ...rosoft_Compute_locations_eastus_vmSizes.json |   28 +
 .../compute/fixtures/ecs/create_public_ip.xml   |    6 +
 .../fixtures/profitbricks/attach_volume.json    |   34 +
 .../fixtures/profitbricks/attach_volume.xml     |   12 -
 .../fixtures/profitbricks/create_node.json      |   37 +
 .../fixtures/profitbricks/create_node.xml       |   13 -
 .../fixtures/profitbricks/create_volume.json    |   35 +
 .../fixtures/profitbricks/create_volume.xml     |   13 -
 .../profitbricks/create_volume_snapshot.json    |   30 +
 .../fixtures/profitbricks/destroy_node.xml      |   12 -
 .../fixtures/profitbricks/destroy_volume.xml    |   12 -
 .../fixtures/profitbricks/detach_volume.xml     |   12 -
 .../profitbricks/ex_clear_datacenter.xml        |   12 -
 .../profitbricks/ex_create_datacenter.json      |   20 +
 .../profitbricks/ex_create_datacenter.xml       |   13 -
 .../profitbricks/ex_create_firewall_rule.json   |   24 +
 .../profitbricks/ex_create_ip_block.json        |   22 +
 .../fixtures/profitbricks/ex_create_lan.json    |   17 +
 .../profitbricks/ex_create_load_balancer.json   |   18 +
 .../ex_create_network_interface.json            |   22 +
 .../ex_create_network_interface.xml             |   13 -
 .../profitbricks/ex_describe_datacenter.json    |  401 ++
 .../profitbricks/ex_describe_datacenter.xml     |   15 -
 .../profitbricks/ex_describe_firewall_rule.json |   24 +
 .../profitbricks/ex_describe_image.json         |   32 +
 .../profitbricks/ex_describe_ip_block.json      |   21 +
 .../fixtures/profitbricks/ex_describe_lan.json  |   24 +
 .../profitbricks/ex_describe_load_balancer.json |   25 +
 .../profitbricks/ex_describe_location.json      |   12 +
 .../ex_describe_network_interface.json          |   31 +
 .../ex_describe_network_interface.xml           |   26 -
 .../fixtures/profitbricks/ex_describe_node.json |  111 +
 .../fixtures/profitbricks/ex_describe_node.xml  |   77 -
 .../profitbricks/ex_describe_snapshot.json      |   30 +
 .../profitbricks/ex_describe_volume.json        |   35 +
 .../profitbricks/ex_describe_volume.xml         |   22 -
 .../profitbricks/ex_destroy_datacenter.xml      |   10 -
 .../ex_destroy_network_interface.xml            |   12 -
 .../profitbricks/ex_list_attached_volumes.json  |  112 +
 .../profitbricks/ex_list_datacenters.json       |   52 +
 .../profitbricks/ex_list_datacenters.xml        |   19 -
 .../profitbricks/ex_list_firewall_rules.json    |   79 +
 .../profitbricks/ex_list_ip_blocks.json         |   50 +
 .../fixtures/profitbricks/ex_list_lans.json     |  157 +
 .../ex_list_load_balanced_nics.json             |   69 +
 .../profitbricks/ex_list_load_balancers.json    |  216 +
 .../ex_list_network_interfaces.json             |   69 +
 .../profitbricks/ex_list_network_interfaces.xml |   75 -
 .../profitbricks/ex_rename_datacenter.json      |   46 +
 .../profitbricks/ex_set_inet_access.json        |   31 +
 .../fixtures/profitbricks/ex_start_node.xml     |   10 -
 .../fixtures/profitbricks/ex_stop_node.xml      |   10 -
 .../profitbricks/ex_update_datacenter.xml       |   12 -
 .../profitbricks/ex_update_firewall_rule.json   |   25 +
 .../fixtures/profitbricks/ex_update_image.json  |   32 +
 .../fixtures/profitbricks/ex_update_lan.json    |   24 +
 .../profitbricks/ex_update_load_balancer.json   |   18 +
 .../ex_update_network_interface.json            |   31 +
 .../ex_update_network_interface.xml             |   12 -
 .../fixtures/profitbricks/ex_update_node.json   |   45 +
 .../fixtures/profitbricks/ex_update_node.xml    |   12 -
 .../profitbricks/ex_update_snapshot.json        |   30 +
 .../fixtures/profitbricks/ex_update_volume.json |   35 +
 .../fixtures/profitbricks/ex_update_volume.xml  |   12 -
 .../fixtures/profitbricks/list_images.json      |  199 +
 .../fixtures/profitbricks/list_images.xml       |   43 -
 .../fixtures/profitbricks/list_locations.json   |   43 +
 .../fixtures/profitbricks/list_nodes.json       |  169 +
 .../fixtures/profitbricks/list_nodes.xml        |  172 -
 .../fixtures/profitbricks/list_snapshots.json   |   37 +
 .../fixtures/profitbricks/list_volumes.json     |  112 +
 .../fixtures/profitbricks/list_volumes.xml      |   66 -
 .../fixtures/profitbricks/reboot_node.xml       |   10 -
 libcloud/test/compute/test_azure_arm.py         |   69 +
 libcloud/test/compute/test_ecs.py               |   12 +-
 libcloud/test/compute/test_profitbricks.py      | 5377 ++++++++++++++++--
 .../alb/describe_load_balancer_listeters.xml    |   27 +
 .../alb/describe_load_balancer_rules.xml        |   21 +
 .../describe_load_balancer_target_groups.xml    |   29 +
 .../fixtures/alb/describe_load_balancers.xml    |   31 +
 .../loadbalancer/fixtures/alb/describe_tags.xml |   18 +
 .../fixtures/alb/describe_target_health.xml     |   19 +
 libcloud/test/loadbalancer/test_alb.py          |  159 +
 libcloud/test/secrets.py-dist                   |    1 +
 122 files changed, 13654 insertions(+), 1933 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/libcloud/blob/4284c31a/libcloud/common/dimensiondata.py
----------------------------------------------------------------------


[39/40] libcloud git commit: Merge branch 'ngoc_images' of https://github.com/samuelchong/libcloud into ngoc_images Closes #953

Posted by an...@apache.org.
Merge branch 'ngoc_images' of https://github.com/samuelchong/libcloud into ngoc_images
Closes #953


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

Branch: refs/heads/trunk
Commit: a77e418bd8db1bebfcdb089c44178bc7bf5d3993
Parents: 5a1eeae 739a820
Author: Samuel Chong <sa...@gmail.com>
Authored: Fri Dec 2 13:52:14 2016 +1100
Committer: Anthony Shaw <an...@apache.org>
Committed: Fri Dec 2 15:31:19 2016 +1100

----------------------------------------------------------------------
 CHANGES.rst                     |  4 ++++
 doap_libcloud.rdf               |  7 +++++++
 libcloud/compute/drivers/gce.py | 32 +++++++++++++++++++-------------
 libcloud/test/secrets.py-dist   |  2 +-
 4 files changed, 31 insertions(+), 14 deletions(-)
----------------------------------------------------------------------