Repository: libcloud
Updated Branches:
  refs/heads/trunk 9908ce12d -> 03733cc12


Adding tests and documentation to firewall rules/anti affinity


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

Branch: refs/heads/trunk
Commit: 02ce76d9ad7e2eab4073f80ab80fdffe153b5c19
Parents: a88cd53
Author: Jeffrey Dunham <jeffrey.a.dun...@gmail.com>
Authored: Thu Mar 24 19:00:39 2016 -0400
Committer: anthony-shaw <anthony.p.s...@gmail.com>
Committed: Sat Mar 26 21:04:19 2016 +1100

----------------------------------------------------------------------
 libcloud/common/dimensiondata.py                |   5 +-
 libcloud/compute/drivers/dimensiondata.py       |  60 ++++++-
 ...a_9cbc_8dabe5a7d0e4_network_firewallRule.xml |  52 +++++-
 ...dabe5a7d0e4_server_antiAffinityRule_list.xml |  42 +++++
 ...4_server_antiAffinityRule_list_PAGINATED.xml |  42 +++++
 ...cbc_8dabe5a7d0e4_antiAffinityRule_create.xml |  11 ++
 ...dabe5a7d0e4_antiAffinityRule_create_FAIL.xml |   7 +
 ...cbc_8dabe5a7d0e4_antiAffinityRule_delete.xml |   7 +
 ...dabe5a7d0e4_antiAffinityRule_delete_FAIL.xml |   7 +
 libcloud/test/compute/test_dimensiondata.py     | 179 +++++++++++++++++++
 10 files changed, 400 insertions(+), 12 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/libcloud/blob/02ce76d9/libcloud/common/dimensiondata.py
----------------------------------------------------------------------
diff --git a/libcloud/common/dimensiondata.py b/libcloud/common/dimensiondata.py
index ffa5d3d..2557e29 100644
--- a/libcloud/common/dimensiondata.py
+++ b/libcloud/common/dimensiondata.py
@@ -446,8 +446,9 @@ class DimensionDataConnection(ConnectionUserAndKey):
 
         while paged_resp.get('pageCount') >= paged_resp.get('pageSize'):
             params['pageNumber'] = int(paged_resp.get('pageNumber')) + 1
-            paged_resp = self._list_nodes_single_page(action, params, data,
-                                                      headers, method).object
+            paged_resp = self.request_with_orgId_api_2(action, params,
+                                                       data, headers,
+                                                       method).object
             yield paged_resp
 
     def get_resource_path_api_1(self):

http://git-wip-us.apache.org/repos/asf/libcloud/blob/02ce76d9/libcloud/compute/drivers/dimensiondata.py
----------------------------------------------------------------------
diff --git a/libcloud/compute/drivers/dimensiondata.py 
b/libcloud/compute/drivers/dimensiondata.py
index 4b999c2..05c6482 100644
--- a/libcloud/compute/drivers/dimensiondata.py
+++ b/libcloud/compute/drivers/dimensiondata.py
@@ -688,6 +688,17 @@ class DimensionDataNodeDriver(NodeDriver):
         return response_code in ['IN_PROGRESS', 'SUCCESS']
 
     def ex_create_anti_affinity_rule(self, node_list):
+        """
+        Create an anti affinity rule given a list of nodes
+        Anti affinity rules ensure that servers will not reside
+        on the same VMware ESX host
+
+        :param node_list: The list of nodes to create a rule for
+        :type  node_list: ``list`` of :class:`Node` or
+                          ``list`` of ``str``
+
+        :rtype: ``bool``
+        """
         if not isinstance(node_list, (list, tuple)):
             raise TypeError("Node list must be a list or a tuple.")
         anti_affinity_xml_request = ET.Element('NewAntiAffinityRule',
@@ -703,6 +714,15 @@ class DimensionDataNodeDriver(NodeDriver):
         return response_code in ['IN_PROGRESS', 'SUCCESS']
 
     def ex_delete_anti_affinity_rule(self, anti_affinity_rule):
+        """
+        Remove anti affinity rule
+
+        :param anti_affinity_rule: The anti affinity rule to delete
+        :type  anti_affinity_rule: :class:`DimensionDataAntiAffinityRule` or
+                                   ``str``
+
+        :rtype: ``bool``
+        """
         rule_id = self._anti_affinity_rule_to_anti_affinity_rule_id(
             anti_affinity_rule)
         result = self.connection.request_with_orgId_api_1(
@@ -712,10 +732,34 @@ class DimensionDataNodeDriver(NodeDriver):
         return response_code in ['IN_PROGRESS', 'SUCCESS']
 
     def ex_list_anti_affinity_rules(self, network=None, network_domain=None,
-                                    node=None, ex_filter_id=None,
-                                    ex_filter_state=None,
-                                    return_generator=False):
+                                    node=None, filter_id=None,
+                                    filter_state=None):
+        """
+        List anti affinity rules for a network, network domain, or node
+
+        :param network: The network to list anti affinity rules for
+                        One of network, network_domain, or node is required
+        :type  network: :class:`DimensionDataNetwork` or ``str``
+
+        :param network_domain: The network domain to list anti affinity rules
+                               One of network, network_domain,
+                               or node is required
+        :type  network_domain: :class:`DimensionDataNetworkDomain` or ``str``
+
+        :param node: The node to list anti affinity rules for
+                     One of network, netwok_domain, or node is required
+        :type  node: :class:`Node` or ``str``
 
+        :param filter_id: This will allow you to filter the rules
+                          by this node id
+        :type  filter_id: ``str``
+
+        :type  filter_state: This will allow you to filter rules by
+                             node state (i.e. NORMAL)
+        :type  filter_state: ``str``
+
+        :rtype: ``list`` of :class:`DimensionDataAntiAffinityRule`
+        """
         not_none_arguments = [key
                               for key in (network, network_domain, node)
                               if key is not None]
@@ -732,11 +776,11 @@ class DimensionDataNodeDriver(NodeDriver):
                 self._network_to_network_id(network)
         if node is not None:
             params['serverId'] = \
-                self._node_to_node_id(network_domain)
-        if ex_filter_id is not None:
-            params['id'] = ex_filter_id
-        if ex_filter_state is not None:
-            params['state'] = ex_filter_state
+                self._node_to_node_id(node)
+        if filter_id is not None:
+            params['id'] = filter_id
+        if filter_state is not None:
+            params['state'] = filter_state
 
         paged_result = self.connection.paginated_request_with_orgId_api_2(
             'server/antiAffinityRule',

http://git-wip-us.apache.org/repos/asf/libcloud/blob/02ce76d9/libcloud/test/compute/fixtures/dimensiondata/caas_2_1_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_firewallRule.xml
----------------------------------------------------------------------
diff --git 
a/libcloud/test/compute/fixtures/dimensiondata/caas_2_1_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_firewallRule.xml
 
b/libcloud/test/compute/fixtures/dimensiondata/caas_2_1_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_firewallRule.xml
index fb5b6ed..536b350 100644
--- 
a/libcloud/test/compute/fixtures/dimensiondata/caas_2_1_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_firewallRule.xml
+++ 
b/libcloud/test/compute/fixtures/dimensiondata/caas_2_1_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_firewallRule.xml
@@ -214,12 +214,60 @@
         <ipVersion>IPV6</ipVersion>
         <protocol>TCP</protocol>
         <source>
-            <ip address="2607:f480:111:1336:6503:544c:74a6:3a28"/>            
+            <ip address="2607:f480:111:1336:6503:544c:74a6:3a28"/>
         </source>
         <destination>
             <ip address="ANY"/>
         </destination>
         <enabled>true</enabled>
         <state>NORMAL</state>
+      </firewallRule>
+      <firewallRule id="ce250bd3-0e45-4c13-a6d2-74e0657ef699" 
datacenterId="NA9" ruleType="CLIENT_RULE">
+        <networkDomainId>423c4386-87b4-43c4-9604-88ae237bfc7f</networkDomainId>
+        <name>RULE_WITH_SOURCE_AND_DEST_IP_ONLY</name>
+        <action>ACCEPT_DECISIVELY</action>
+        <ipVersion>IPV4</ipVersion>
+        <protocol>TCP</protocol>
+        <source>
+          <ip address="10.10.10.15"/>
+        </source>
+        <destination>
+          <ip address="10.10.10.14"/>
+        </destination>
+        <enabled>true</enabled>
+        <state>NORMAL</state>
+      </firewallRule>
+      <firewallRule id="ce250bd3-0e45-4c13-a6d2-74e0657ef699" 
datacenterId="NA9" ruleType="CLIENT_RULE">
+        <networkDomainId>423c4386-87b4-43c4-9604-88ae237bfc7f</networkDomainId>
+        <name>RULE_WITH_DEST_IP_NO_PORT</name>
+        <action>ACCEPT_DECISIVELY</action>
+        <ipVersion>IPV4</ipVersion>
+        <protocol>TCP</protocol>
+        <source>
+          <ip address="10.10.10.15"/>
+        </source>
+        <destination>
+          <ip address="10.10.10.14"/>
+          <port begin="40000" end="40005"/>
+        </destination>
+        <enabled>true</enabled>
+        <state>NORMAL</state>
+      </firewallRule>
+      <firewallRule id="ce250bd3-0e45-4c13-a6d2-74e0657ef700" 
datacenterId="NA9" ruleType="CLIENT_RULE">
+        <networkDomainId>423c4386-87b4-43c4-9604-88ae237bfc7f</networkDomainId>
+        <name>RULE_WITH_SOURCE_AND_DEST</name>
+        <action>ACCEPT_DECISIVELY</action>
+        <ipVersion>IPV4</ipVersion>
+        <protocol>TCP</protocol>
+        <source>
+          <ip address="10.10.10.0" prefixSize="24"/>
+          <port begin="40000" end="40005"/>
+      </source>
+      <destination>
+        <ip address="10.10.10.0" prefixSize="24"/>
+        <port begin="40000"/>
+      </destination>
+      <enabled>true</enabled>
+      <state>NORMAL</state>
     </firewallRule>
-</firewallRules>
\ No newline at end of file
+</firewallRules>

http://git-wip-us.apache.org/repos/asf/libcloud/blob/02ce76d9/libcloud/test/compute/fixtures/dimensiondata/caas_2_1_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_antiAffinityRule_list.xml
----------------------------------------------------------------------
diff --git 
a/libcloud/test/compute/fixtures/dimensiondata/caas_2_1_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_antiAffinityRule_list.xml
 
b/libcloud/test/compute/fixtures/dimensiondata/caas_2_1_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_antiAffinityRule_list.xml
new file mode 100644
index 0000000..8179051
--- /dev/null
+++ 
b/libcloud/test/compute/fixtures/dimensiondata/caas_2_1_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_antiAffinityRule_list.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<antiAffinityRules xmlns="urn:didata.com:api:cloud:types" pageNumber="1" 
pageCount="2" totalCount="2" pageSize="250">
+  <antiAffinityRule id="07e3621a-a920-4a9a-943c-d8021f27f418" state="NORMAL" 
created="2016-03-24T00:03:27.000Z" datacenterId="NA9">
+    <serverSummary id="22f3544a-c874-4930-a31c-e9e513e51114">
+      <name>ansible-test-image-rhel6</name>
+      <description>my new node</description>
+      <networkingDetails>
+        <networkInfo networkDomainId="423c4386-87b4-43c4-9604-88ae237bfc7f" 
networkDomainName="Deloitte Test">
+          <primaryNic id="aafffb27-f16b-4757-9b63-ef7d8acd9c7f" 
privateIpv4="172.16.1.8" ipv6="2607:f480:111:1423:1b57:e47a:c212:257d" 
vlanId="bd6fbee5-17db-49f8-b1f5-3b213cea3061" vlanName="deloitte-test"/>        
</networkInfo>
+      </networkingDetails>
+    </serverSummary>
+    <serverSummary id="5718d174-31d4-4d49-b1c6-fcb0d782f233">
+      <name>ansible-custom-image-test-UAT</name>
+      <description>my new node</description>
+      <networkingDetails>
+        <networkInfo networkDomainId="423c4386-87b4-43c4-9604-88ae237bfc7f" 
networkDomainName="Deloitte Test">
+          <primaryNic id="b359cea3-4452-46fe-b30b-b3ce839cde9b" 
privateIpv4="172.16.1.9" ipv6="2607:f480:111:1423:7fa7:9a9b:ecb9:882e" 
vlanId="bd6fbee5-17db-49f8-b1f5-3b213cea3061" vlanName="deloitte-test"/>
+        </networkInfo>
+      </networkingDetails>
+    </serverSummary>
+  </antiAffinityRule>
+  <antiAffinityRule id="5e10b1ab-68f2-4a8b-a49c-d88d623db665" state="NORMAL" 
created="2016-03-24T00:07:39.000Z" datacenterId="NA9">
+    <serverSummary id="9f8b5428-bac3-4cf9-adda-62f57fb38671">
+      <name>rhel-ansible-full-test</name>
+      <description>RHEL Ansible Test</description>
+      <networkingDetails>
+        <networkInfo networkDomainId="423c4386-87b4-43c4-9604-88ae237bfc7f" 
networkDomainName="Deloitte Test">
+          <primaryNic id="e081e784-5768-472c-b7f3-353e1646edc8" 
privateIpv4="172.16.1.15" ipv6="2607:f480:111:1423:70c9:9216:f7bf:dcf6" 
vlanId="bd6fbee5-17db-49f8-b1f5-3b213cea3061" vlanName="deloitte-test"/>
+        </networkInfo>
+      </networkingDetails>
+    </serverSummary>
+    <serverSummary id="feee5cd2-d83b-4b80-913d-0bf26c838a33">
+      <name>rhel-ansible-full-test</name>
+      <description>RHEL Ansible Test</description>
+      <networkingDetails>
+        <networkInfo networkDomainId="423c4386-87b4-43c4-9604-88ae237bfc7f" 
networkDomainName="Deloitte Test">
+          <primaryNic id="3278f833-9535-405c-91b8-0a0470f58aae" 
privateIpv4="172.16.1.17" ipv6="2607:f480:111:1423:3081:71a8:4c52:a8a" 
vlanId="bd6fbee5-17db-49f8-b1f5-3b213cea3061" vlanName="deloitte-test"/>
+        </networkInfo>
+      </networkingDetails>
+    </serverSummary>
+  </antiAffinityRule>
+</antiAffinityRules>

http://git-wip-us.apache.org/repos/asf/libcloud/blob/02ce76d9/libcloud/test/compute/fixtures/dimensiondata/caas_2_1_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_antiAffinityRule_list_PAGINATED.xml
----------------------------------------------------------------------
diff --git 
a/libcloud/test/compute/fixtures/dimensiondata/caas_2_1_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_antiAffinityRule_list_PAGINATED.xml
 
b/libcloud/test/compute/fixtures/dimensiondata/caas_2_1_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_antiAffinityRule_list_PAGINATED.xml
new file mode 100644
index 0000000..d765264
--- /dev/null
+++ 
b/libcloud/test/compute/fixtures/dimensiondata/caas_2_1_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_antiAffinityRule_list_PAGINATED.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<antiAffinityRules xmlns="urn:didata.com:api:cloud:types" pageNumber="1" 
pageCount="2" totalCount="2" pageSize="2">
+  <antiAffinityRule id="07e3621a-a920-4a9a-943c-d8021f27f418" state="NORMAL" 
created="2016-03-24T00:03:27.000Z" datacenterId="NA9">
+    <serverSummary id="22f3544a-c874-4930-a31c-e9e513e51114">
+      <name>ansible-test-image-rhel6</name>
+      <description>my new node</description>
+      <networkingDetails>
+        <networkInfo networkDomainId="423c4386-87b4-43c4-9604-88ae237bfc7f" 
networkDomainName="Deloitte Test">
+          <primaryNic id="aafffb27-f16b-4757-9b63-ef7d8acd9c7f" 
privateIpv4="172.16.1.8" ipv6="2607:f480:111:1423:1b57:e47a:c212:257d" 
vlanId="bd6fbee5-17db-49f8-b1f5-3b213cea3061" vlanName="deloitte-test"/>        
</networkInfo>
+      </networkingDetails>
+    </serverSummary>
+    <serverSummary id="5718d174-31d4-4d49-b1c6-fcb0d782f233">
+      <name>ansible-custom-image-test-UAT</name>
+      <description>my new node</description>
+      <networkingDetails>
+        <networkInfo networkDomainId="423c4386-87b4-43c4-9604-88ae237bfc7f" 
networkDomainName="Deloitte Test">
+          <primaryNic id="b359cea3-4452-46fe-b30b-b3ce839cde9b" 
privateIpv4="172.16.1.9" ipv6="2607:f480:111:1423:7fa7:9a9b:ecb9:882e" 
vlanId="bd6fbee5-17db-49f8-b1f5-3b213cea3061" vlanName="deloitte-test"/>
+        </networkInfo>
+      </networkingDetails>
+    </serverSummary>
+  </antiAffinityRule>
+  <antiAffinityRule id="5e10b1ab-68f2-4a8b-a49c-d88d623db665" state="NORMAL" 
created="2016-03-24T00:07:39.000Z" datacenterId="NA9">
+    <serverSummary id="9f8b5428-bac3-4cf9-adda-62f57fb38671">
+      <name>rhel-ansible-full-test</name>
+      <description>RHEL Ansible Test</description>
+      <networkingDetails>
+        <networkInfo networkDomainId="423c4386-87b4-43c4-9604-88ae237bfc7f" 
networkDomainName="Deloitte Test">
+          <primaryNic id="e081e784-5768-472c-b7f3-353e1646edc8" 
privateIpv4="172.16.1.15" ipv6="2607:f480:111:1423:70c9:9216:f7bf:dcf6" 
vlanId="bd6fbee5-17db-49f8-b1f5-3b213cea3061" vlanName="deloitte-test"/>
+        </networkInfo>
+      </networkingDetails>
+    </serverSummary>
+    <serverSummary id="feee5cd2-d83b-4b80-913d-0bf26c838a33">
+      <name>rhel-ansible-full-test</name>
+      <description>RHEL Ansible Test</description>
+      <networkingDetails>
+        <networkInfo networkDomainId="423c4386-87b4-43c4-9604-88ae237bfc7f" 
networkDomainName="Deloitte Test">
+          <primaryNic id="3278f833-9535-405c-91b8-0a0470f58aae" 
privateIpv4="172.16.1.17" ipv6="2607:f480:111:1423:3081:71a8:4c52:a8a" 
vlanId="bd6fbee5-17db-49f8-b1f5-3b213cea3061" vlanName="deloitte-test"/>
+        </networkInfo>
+      </networkingDetails>
+    </serverSummary>
+  </antiAffinityRule>
+</antiAffinityRules>

http://git-wip-us.apache.org/repos/asf/libcloud/blob/02ce76d9/libcloud/test/compute/fixtures/dimensiondata/oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_antiAffinityRule_create.xml
----------------------------------------------------------------------
diff --git 
a/libcloud/test/compute/fixtures/dimensiondata/oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_antiAffinityRule_create.xml
 
b/libcloud/test/compute/fixtures/dimensiondata/oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_antiAffinityRule_create.xml
new file mode 100644
index 0000000..993b85d
--- /dev/null
+++ 
b/libcloud/test/compute/fixtures/dimensiondata/oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_antiAffinityRule_create.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<ns5:Status xmlns:ns16="http://oec.api.opsource.net/schemas/storage"; 
xmlns="http://oec.api.opsource.net/schemas/server"; 
xmlns:ns14="http://oec.api.opsource.net/schemas/serverbootstrap"; 
xmlns:ns15="http://oec.api.opsource.net/schemas/multigeo"; 
xmlns:ns9="http://oec.api.opsource.net/schemas/admin"; 
xmlns:ns5="http://oec.api.opsource.net/schemas/general"; 
xmlns:ns12="http://oec.api.opsource.net/schemas/whitelabel"; 
xmlns:ns13="http://oec.api.opsource.net/schemas/reset"; 
xmlns:ns6="http://oec.api.opsource.net/schemas/vip"; 
xmlns:ns7="http://oec.api.opsource.net/schemas/datacenter"; 
xmlns:ns10="http://oec.api.opsource.net/schemas/backup"; 
xmlns:ns8="http://oec.api.opsource.net/schemas/manualimport"; 
xmlns:ns11="http://oec.api.opsource.net/schemas/support"; 
xmlns:ns2="http://oec.api.opsource.net/schemas/network"; 
xmlns:ns4="http://oec.api.opsource.net/schemas/directory"; 
xmlns:ns3="http://oec.api.opsource.net/schemas/organization";>
+    <ns5:operation>Create Anti Affinity Rule</ns5:operation>
+    <ns5:result>SUCCESS</ns5:result>
+    <ns5:resultDetail>Request to create Server Anti-Affinity Rule between 
'rhel-ansible-full-test' and 'rhel-ansible-full-test' on 'Deloitte Test' has 
been accepted and is being processed.</ns5:resultDetail>
+    <ns5:resultCode>REASON_0</ns5:resultCode>
+    <ns5:additionalInformation name="antiaffinityrule.id">
+        <ns5:value>5e10b1ab-68f2-4a8b-a49c-d88d623db665</ns5:value>
+    </ns5:additionalInformation>
+</ns5:Status>
+

http://git-wip-us.apache.org/repos/asf/libcloud/blob/02ce76d9/libcloud/test/compute/fixtures/dimensiondata/oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_antiAffinityRule_create_FAIL.xml
----------------------------------------------------------------------
diff --git 
a/libcloud/test/compute/fixtures/dimensiondata/oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_antiAffinityRule_create_FAIL.xml
 
b/libcloud/test/compute/fixtures/dimensiondata/oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_antiAffinityRule_create_FAIL.xml
new file mode 100644
index 0000000..eecc69d
--- /dev/null
+++ 
b/libcloud/test/compute/fixtures/dimensiondata/oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_antiAffinityRule_create_FAIL.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<ns5:Status xmlns:ns16="http://oec.api.opsource.net/schemas/storage"; 
xmlns="http://oec.api.opsource.net/schemas/server"; 
xmlns:ns14="http://oec.api.opsource.net/schemas/serverbootstrap"; 
xmlns:ns15="http://oec.api.opsource.net/schemas/multigeo"; 
xmlns:ns9="http://oec.api.opsource.net/schemas/admin"; 
xmlns:ns5="http://oec.api.opsource.net/schemas/general"; 
xmlns:ns12="http://oec.api.opsource.net/schemas/whitelabel"; 
xmlns:ns13="http://oec.api.opsource.net/schemas/reset"; 
xmlns:ns6="http://oec.api.opsource.net/schemas/vip"; 
xmlns:ns7="http://oec.api.opsource.net/schemas/datacenter"; 
xmlns:ns10="http://oec.api.opsource.net/schemas/backup"; 
xmlns:ns8="http://oec.api.opsource.net/schemas/manualimport"; 
xmlns:ns11="http://oec.api.opsource.net/schemas/support"; 
xmlns:ns2="http://oec.api.opsource.net/schemas/network"; 
xmlns:ns4="http://oec.api.opsource.net/schemas/directory"; 
xmlns:ns3="http://oec.api.opsource.net/schemas/organization";>
+  <ns5:operation>Create Anti Affinity Rule</ns5:operation>
+  <ns5:result>ERROR</ns5:result>
+  <ns5:resultDetail>Server 'ansible-test-image-rhel6' (id 
22f3544a-c874-4930-a31c-e9e513e51114) is already used in another Anti-Affinity 
Rule (id 07e3621a-a920-4a9a-943c-d8021f27f418).</ns5:resultDetail>
+  <ns5:resultCode>REASON_692</ns5:resultCode>
+</ns5:Status>

http://git-wip-us.apache.org/repos/asf/libcloud/blob/02ce76d9/libcloud/test/compute/fixtures/dimensiondata/oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_antiAffinityRule_delete.xml
----------------------------------------------------------------------
diff --git 
a/libcloud/test/compute/fixtures/dimensiondata/oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_antiAffinityRule_delete.xml
 
b/libcloud/test/compute/fixtures/dimensiondata/oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_antiAffinityRule_delete.xml
new file mode 100644
index 0000000..0d73a13
--- /dev/null
+++ 
b/libcloud/test/compute/fixtures/dimensiondata/oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_antiAffinityRule_delete.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<ns5:Status xmlns:ns16="http://oec.api.opsource.net/schemas/storage"; 
xmlns="http://oec.api.opsource.net/schemas/server"; 
xmlns:ns14="http://oec.api.opsource.net/schemas/serverbootstrap"; 
xmlns:ns15="http://oec.api.opsource.net/schemas/multigeo"; 
xmlns:ns9="http://oec.api.opsource.net/schemas/admin"; 
xmlns:ns5="http://oec.api.opsource.net/schemas/general"; 
xmlns:ns12="http://oec.api.opsource.net/schemas/whitelabel"; 
xmlns:ns13="http://oec.api.opsource.net/schemas/reset"; 
xmlns:ns6="http://oec.api.opsource.net/schemas/vip"; 
xmlns:ns7="http://oec.api.opsource.net/schemas/datacenter"; 
xmlns:ns10="http://oec.api.opsource.net/schemas/backup"; 
xmlns:ns8="http://oec.api.opsource.net/schemas/manualimport"; 
xmlns:ns11="http://oec.api.opsource.net/schemas/support"; 
xmlns:ns2="http://oec.api.opsource.net/schemas/network"; 
xmlns:ns4="http://oec.api.opsource.net/schemas/directory"; 
xmlns:ns3="http://oec.api.opsource.net/schemas/organization";>
+    <ns5:operation>Delete Anti Affinity Rule</ns5:operation>
+    <ns5:result>SUCCESS</ns5:result>
+    <ns5:resultDetail>Request to delete Server Anti-Affinity Rule between 
'ansible-test-image-rhel6' and 'ansible-custom-image-test-UAT' on 'Deloitte 
Test' has been accepted and is being processed.</ns5:resultDetail>
+    <ns5:resultCode>REASON_0</ns5:resultCode>
+</ns5:Status>

http://git-wip-us.apache.org/repos/asf/libcloud/blob/02ce76d9/libcloud/test/compute/fixtures/dimensiondata/oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_antiAffinityRule_delete_FAIL.xml
----------------------------------------------------------------------
diff --git 
a/libcloud/test/compute/fixtures/dimensiondata/oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_antiAffinityRule_delete_FAIL.xml
 
b/libcloud/test/compute/fixtures/dimensiondata/oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_antiAffinityRule_delete_FAIL.xml
new file mode 100644
index 0000000..187f482
--- /dev/null
+++ 
b/libcloud/test/compute/fixtures/dimensiondata/oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_antiAffinityRule_delete_FAIL.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<ns5:Status xmlns:ns16="http://oec.api.opsource.net/schemas/storage"; 
xmlns="http://oec.api.opsource.net/schemas/server"; 
xmlns:ns14="http://oec.api.opsource.net/schemas/serverbootstrap"; 
xmlns:ns15="http://oec.api.opsource.net/schemas/multigeo"; 
xmlns:ns9="http://oec.api.opsource.net/schemas/admin"; 
xmlns:ns5="http://oec.api.opsource.net/schemas/general"; 
xmlns:ns12="http://oec.api.opsource.net/schemas/whitelabel"; 
xmlns:ns13="http://oec.api.opsource.net/schemas/reset"; 
xmlns:ns6="http://oec.api.opsource.net/schemas/vip"; 
xmlns:ns7="http://oec.api.opsource.net/schemas/datacenter"; 
xmlns:ns10="http://oec.api.opsource.net/schemas/backup"; 
xmlns:ns8="http://oec.api.opsource.net/schemas/manualimport"; 
xmlns:ns11="http://oec.api.opsource.net/schemas/support"; 
xmlns:ns2="http://oec.api.opsource.net/schemas/network"; 
xmlns:ns4="http://oec.api.opsource.net/schemas/directory"; 
xmlns:ns3="http://oec.api.opsource.net/schemas/organization";>
+    <ns5:operation>Delete Anti Affinity Rule</ns5:operation>
+    <ns5:result>ERROR</ns5:result>
+    <ns5:resultDetail>Could not find Anti Affinity Rule with Id 
07e3621a-a920-4a9a-943c-d8021f27f418</ns5:resultDetail>
+    <ns5:resultCode>REASON_693</ns5:resultCode>
+</ns5:Status>

http://git-wip-us.apache.org/repos/asf/libcloud/blob/02ce76d9/libcloud/test/compute/test_dimensiondata.py
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/test_dimensiondata.py 
b/libcloud/test/compute/test_dimensiondata.py
index 8ec9d27..0b81317 100644
--- a/libcloud/test/compute/test_dimensiondata.py
+++ b/libcloud/test/compute/test_dimensiondata.py
@@ -665,6 +665,36 @@ class DimensionDataTests(unittest.TestCase, TestCaseMixin):
         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_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')
@@ -790,6 +820,97 @@ class DimensionDataTests(unittest.TestCase, TestCaseMixin):
         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_priv_location_to_location_id(self):
         location = self.driver.ex_get_location_by_id('NA9')
         self.assertEqual(
@@ -979,6 +1100,30 @@ class DimensionDataMockHttp(MockHttp):
                 
'oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_e75ead52_692f_4314_8725_c8a4f4d13a87_POST.xml')
             return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
+    def _oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_antiAffinityRule(self, 
method, url, body, headers):
+        body = self.fixtures.load(
+            
'oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_antiAffinityRule_create.xml'
+        )
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+    def 
_oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_antiAffinityRule_FAIL_EXISTING(self,
 method, url, body, headers):
+        body = self.fixtures.load(
+            
'oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_antiAffinityRule_create_FAIL.xml'
+        )
+        return (httplib.BAD_REQUEST, body, {}, httplib.responses[httplib.OK])
+
+    def 
_oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_antiAffinityRule_07e3621a_a920_4a9a_943c_d8021f27f418(self,
 method, url, body, headers):
+        body = self.fixtures.load(
+            
'oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_antiAffinityRule_delete.xml'
+        )
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+    def 
_oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_antiAffinityRule_07e3621a_a920_4a9a_943c_d8021f27f418_FAIL(self,
 method, url, body, headers):
+        body = self.fixtures.load(
+            
'oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_antiAffinityRule_delete_FAIL.xml'
+        )
+        return (httplib.BAD_REQUEST, body, {}, httplib.responses[httplib.OK])
+
     def _caas_2_1_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server(self, method, 
url, body, headers):
         body = self.fixtures.load(
             'caas_2_1_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server.xml')
@@ -1069,6 +1214,40 @@ class DimensionDataMockHttp(MockHttp):
             'caas_2_1_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_server.xml')
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
+    def 
_caas_2_1_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_antiAffinityRule(self, 
method, url, body, headers):
+        body = self.fixtures.load(
+            
'caas_2_1_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_antiAffinityRule_list.xml'
+        )
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+    def 
_caas_2_1_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_antiAffinityRule_ALLFILTERS(self,
 method, url, body, headers):
+        (_, params) = url.split('?')
+        parameters = params.split('&')
+        for parameter in parameters:
+            (key, value) = parameter.split('=')
+            if key == 'id':
+                assert value == 'FAKE_ID'
+            elif key == 'state':
+                assert value == 'FAKE_STATE'
+            elif key == 'networkDomainId':
+                pass
+            else:
+                raise ValueError("Could not find in url parameters 
{0}:{1}".format(key, value))
+        body = self.fixtures.load(
+            
'caas_2_1_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_antiAffinityRule_list.xml'
+        )
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+    def 
_caas_2_1_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_antiAffinityRule_PAGINATED(self,
 method, url, body, headers):
+        if url.endswith('pageNumber=2'):
+            body = self.fixtures.load(
+                
'caas_2_1_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_antiAffinityRule_list.xml')
+            return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+        else:
+            body = self.fixtures.load(
+                
'caas_2_1_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_server_antiAffinityRule_list_PAGINATED.xml')
+            return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
     def 
_caas_2_1_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_infrastructure_datacenter(self, 
method, url, body, headers):
         if url.endswith('id=NA9'):
             body = self.fixtures.load(

Reply via email to