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 2015/12/06 22:44:04 UTC

[1/3] libcloud git commit: Extended load balancer functionality to support persistence profiles, irules and default monitors.

Repository: libcloud
Updated Branches:
  refs/heads/trunk c7ffbe780 -> 914c4eb3d


Extended load balancer functionality to support persistence profiles, irules and default monitors.

Signed-off-by: Anthony Shaw <an...@gmail.com>


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

Branch: refs/heads/trunk
Commit: 89ad96c7f1d22f220a7c7c247d66caba5891938c
Parents: c7ffbe7
Author: Anthony Shaw <an...@gmail.com>
Authored: Fri Dec 4 16:22:37 2015 +1100
Committer: Anthony Shaw <an...@gmail.com>
Committed: Mon Dec 7 08:44:24 2015 +1100

----------------------------------------------------------------------
 libcloud/common/dimensiondata.py                |  61 +++++++
 libcloud/loadbalancer/drivers/dimensiondata.py  | 159 ++++++++++++++++++-
 ...e4_networkDomainVip_defaultHealthMonitor.xml |  35 ++++
 ...abe5a7d0e4_networkDomainVip_defaultIrule.xml |  47 ++++++
 ...tworkDomainVip_defaultPersistenceProfile.xml |  47 ++++++
 .../test/loadbalancer/test_dimensiondata.py     |  46 ++++++
 6 files changed, 392 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/libcloud/blob/89ad96c7/libcloud/common/dimensiondata.py
----------------------------------------------------------------------
diff --git a/libcloud/common/dimensiondata.py b/libcloud/common/dimensiondata.py
index 4d76d93..a08a4f9 100644
--- a/libcloud/common/dimensiondata.py
+++ b/libcloud/common/dimensiondata.py
@@ -553,3 +553,64 @@ class DimensionDataVirtualListener(object):
                  'status=%s, ip=%s>')
                 % (self.id, self.name,
                    self.status, self.ip))
+
+
+class DimensionDataDefaultHealthMonitor(object):
+    """
+    A default health monitor for a VIP (node, pool or listener)
+    """
+    def __init__(self, id, name, node_compatible, pool_compatible):
+        self.id = id
+        self.name = name
+        self.node_compatible = node_compatible
+        self.pool_compatible = pool_compatible
+
+    def __repr__(self):
+        return (('<DimensionDataDefaultHealthMonitor: id=%s, name=%s>')
+                % (self.id, self.name))
+
+
+class DimensionDataPersistenceProfile(object):
+    """
+    Each Persistence Profile declares the combination of Virtual Listener
+    type and protocol with which it is
+    compatible and whether or not it is compatible as a
+    Fallback Persistence Profile.
+    """
+    def __init__(self, id, name, compatible_listeners, fallback_compatible):
+        self.id = id
+        self.name = name
+        self.compatible_listeners = compatible_listeners
+        self.fallback_compatible = fallback_compatible
+
+    def __repr__(self):
+        return (('<DimensionDataPersistenceProfile: id=%s, name=%s>')
+                % (self.id, self.name))
+
+
+class DimensionDataDefaultiRule(object):
+    """
+    A default iRule for a network domain, can be applied to a listener
+    """
+    def __init__(self, id, name, compatible_listeners):
+        self.id = id
+        self.name = name
+        self.compatible_listeners = compatible_listeners
+
+    def __repr__(self):
+        return (('<DimensionDataDefaultiRule: id=%s, name=%s>')
+                % (self.id, self.name))
+
+
+class DimensionDataVirtualListenerCompatibility(object):
+    """
+    A compatibility preference for a persistence profile
+    """
+    def __init__(self, type, protocol):
+        self.type = type
+        self.protocol = protocol
+
+    def __repr__(self):
+        return (('<DimensionDataVirtualListenerCompatibility: '
+                 'type=%s, protocol=%s>')
+                % (self.type, self.protocol))

http://git-wip-us.apache.org/repos/asf/libcloud/blob/89ad96c7/libcloud/loadbalancer/drivers/dimensiondata.py
----------------------------------------------------------------------
diff --git a/libcloud/loadbalancer/drivers/dimensiondata.py b/libcloud/loadbalancer/drivers/dimensiondata.py
index 38bdf13..462a2b0 100644
--- a/libcloud/loadbalancer/drivers/dimensiondata.py
+++ b/libcloud/loadbalancer/drivers/dimensiondata.py
@@ -23,6 +23,11 @@ from libcloud.common.dimensiondata import DimensionDataPool
 from libcloud.common.dimensiondata import DimensionDataPoolMember
 from libcloud.common.dimensiondata import DimensionDataVirtualListener
 from libcloud.common.dimensiondata import DimensionDataVIPNode
+from libcloud.common.dimensiondata import DimensionDataDefaultHealthMonitor
+from libcloud.common.dimensiondata import DimensionDataPersistenceProfile
+from libcloud.common.dimensiondata import \
+    DimensionDataVirtualListenerCompatibility
+from libcloud.common.dimensiondata import DimensionDataDefaultiRule
 from libcloud.common.dimensiondata import API_ENDPOINTS
 from libcloud.common.dimensiondata import DEFAULT_REGION
 from libcloud.common.dimensiondata import TYPES_URN
@@ -473,6 +478,7 @@ class DimensionDataLBDriver(Driver):
                        name,
                        balancer_method,
                        ex_description,
+                       health_monitors=None,
                        service_down_action='NONE',
                        slow_ramp_time=30):
         """
@@ -490,6 +496,10 @@ class DimensionDataLBDriver(Driver):
         :param ex_description: Description of the node
         :type  ex_description: ``str``
 
+        :param health_monitors: A list of health monitors to use for the pool.
+        :type  health_monitors: ``list`` of
+            :class:`DimensionDataDefaultHealthMonitor`
+
         :param service_down_action: What to do when node
                                     is unavailable NONE, DROP or RESELECT
         :type  service_down_action: ``str``
@@ -510,6 +520,12 @@ class DimensionDataLBDriver(Driver):
             = str(ex_description)
         ET.SubElement(create_node_elm, "loadBalanceMethod") \
             .text = str(balancer_method)
+
+        if health_monitors is not None:
+            for monitor in health_monitors:
+                ET.SubElement(create_node_elm, "healthMonitorId") \
+                    .text = str(monitor.id)
+
         ET.SubElement(create_node_elm, "serviceDownAction") \
             .text = service_down_action
         ET.SubElement(create_node_elm, "slowRampTime").text \
@@ -542,6 +558,9 @@ class DimensionDataLBDriver(Driver):
                                    ex_description,
                                    port,
                                    pool,
+                                   persistence_profile=None,
+                                   fallback_persistence_profile=None,
+                                   irule=None,
                                    protocol='TCP',
                                    connection_limit=25000,
                                    connection_rate_limit=2000,
@@ -561,9 +580,18 @@ class DimensionDataLBDriver(Driver):
         :param port: Description of the node
         :type  port: ``str``
 
-        :param listener_type: The type of balancer, one of STANDARD (default)
-                                or PERFORMANCE_LAYER_4
-        :type  listener_type: ``str``
+        :param pool: The pool to use for the listener
+        :type  pool: :class:`DimensionDataPool`
+
+        :param persistence_profile: Persistence profile
+        :type  persistence_profile: :class:`DimensionDataPersistenceProfile`
+
+        :param fallback_persistence_profile: Fallback persistence profile
+        :type  fallback_persistence_profile:
+            :class:`DimensionDataPersistenceProfile`
+
+        :param irule: The iRule to apply
+        :type  irule: :class:`DimensionDataDefaultiRule`
 
         :param protocol: For STANDARD type, ANY, TCP or UDP
                          for PERFORMANCE_LAYER_4 choice of ANY, TCP, UDP, HTTP
@@ -609,6 +637,15 @@ class DimensionDataLBDriver(Driver):
             .text = source_port_preservation
         ET.SubElement(create_node_elm, "poolId") \
             .text = pool.id
+        if persistence_profile is not None:
+            ET.SubElement(create_node_elm, "persistenceProfileId") \
+                .text = persistence_profile.id
+        if fallback_persistence_profile is not None:
+            ET.SubElement(create_node_elm, "fallbackPersistenceProfileId") \
+                .text = fallback_persistence_profile.id
+        if irule is not None:
+            ET.SubElement(create_node_elm, "iruleId") \
+                .text = irule.id
 
         response = self.connection.request_with_orgId_api_2(
             action='networkDomainVip/createVirtualListener',
@@ -852,6 +889,122 @@ class DimensionDataLBDriver(Driver):
         return self.connection.wait_for_state(state, func, poll_interval,
                                               timeout, *args, **kwargs)
 
+    def ex_get_default_health_monitors(self, network_domain_id):
+        """
+        Get the default health monitors available for a network domain
+
+        :param network_domain_id: The ID of of a ``DimensionDataNetworkDomain``
+        :type  network_domain_id: ``str``
+
+        :rtype: `list` of :class:`DimensionDataDefaultHealthMonitor`
+        """
+        result = self.connection.request_with_orgId_api_2(
+            action='networkDomainVip/defaultHealthMonitor',
+            params={'networkDomainId': network_domain_id},
+            method='GET').object
+        return self._to_health_monitors(result)
+
+    def ex_get_default_persistence_profiles(self, network_domain_id):
+        """
+        Get the default persistence profiles available for a network domain
+
+        :param network_domain_id: The ID of of a ``DimensionDataNetworkDomain``
+        :type  network_domain_id: ``str``
+
+        :rtype: `list` of :class:`DimensionDataPersistenceProfile`
+        """
+        result = self.connection.request_with_orgId_api_2(
+            action='networkDomainVip/defaultPersistenceProfile',
+            params={'networkDomainId': network_domain_id},
+            method='GET').object
+        return self._to_persistence_profiles(result)
+
+    def ex_get_default_irules(self, network_domain_id):
+        """
+        Get the default iRules available for a network domain
+
+        :param network_domain_id: The ID of of a ``DimensionDataNetworkDomain``
+        :type  network_domain_id: ``str``
+
+        :rtype: `list` of :class:`DimensionDataDefaultiRule`
+        """
+        result = self.connection.request_with_orgId_api_2(
+            action='networkDomainVip/defaultIrule',
+            params={'networkDomainId': network_domain_id},
+            method='GET').object
+        return self._to_irules(result)
+
+    def _to_irules(self, object):
+        irules = []
+        matches = object.findall(
+            fixxpath('defaultIrule', TYPES_URN))
+        for element in matches:
+            irules.append(self._to_irule(element))
+        return irules
+
+    def _to_irule(self, element):
+        compatible = []
+        matches = element.findall(
+            fixxpath('virtualListenerCompatibility', TYPES_URN))
+        for match_element in matches:
+            compatible.append(
+                DimensionDataVirtualListenerCompatibility(
+                    type=match_element.get('type'),
+                    protocol=match_element.get('protocol', None)
+                )
+                )
+        irule_element = element.find(fixxpath('irule', TYPES_URN))
+        return DimensionDataDefaultiRule(
+            id=irule_element.get('id'),
+            name=irule_element.get('name'),
+            compatible_listeners=compatible
+        )
+
+    def _to_persistence_profiles(self, object):
+        profiles = []
+        matches = object.findall(
+            fixxpath('defaultPersistenceProfile', TYPES_URN))
+        for element in matches:
+            profiles.append(self._to_persistence_profile(element))
+        return profiles
+
+    def _to_persistence_profile(self, element):
+        compatible = []
+        matches = element.findall(
+            fixxpath('virtualListenerCompatibility', TYPES_URN))
+        for match_element in matches:
+            compatible.append(
+                DimensionDataVirtualListenerCompatibility(
+                    type=match_element.get('type'),
+                    protocol=match_element.get('protocol', None)
+                )
+                )
+
+        return DimensionDataPersistenceProfile(
+            id=element.get('id'),
+            fallback_compatible=bool(element.get('fallbackCompatible')
+                                     == "true"),
+            name=findtext(element, 'name', TYPES_URN),
+            compatible_listeners=compatible
+        )
+
+    def _to_health_monitors(self, object):
+        monitors = []
+        matches = object.findall(fixxpath('defaultHealthMonitor', TYPES_URN))
+        for element in matches:
+            monitors.append(self._to_health_monitor(element))
+        return monitors
+
+    def _to_health_monitor(self, element):
+        return DimensionDataDefaultHealthMonitor(
+            id=element.get('id'),
+            name=findtext(element, 'name', TYPES_URN),
+            node_compatible=bool(
+                findtext(element, 'nodeCompatible', TYPES_URN) == "true"),
+            pool_compatible=bool(
+                findtext(element, 'poolCompatible', TYPES_URN) == "true"),
+        )
+
     def _to_nodes(self, object):
         nodes = []
         for element in object.findall(fixxpath("node", TYPES_URN)):

http://git-wip-us.apache.org/repos/asf/libcloud/blob/89ad96c7/libcloud/test/loadbalancer/fixtures/dimensiondata/caas_2_0_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_defaultHealthMonitor.xml
----------------------------------------------------------------------
diff --git a/libcloud/test/loadbalancer/fixtures/dimensiondata/caas_2_0_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_defaultHealthMonitor.xml b/libcloud/test/loadbalancer/fixtures/dimensiondata/caas_2_0_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_defaultHealthMonitor.xml
new file mode 100644
index 0000000..b24f006
--- /dev/null
+++ b/libcloud/test/loadbalancer/fixtures/dimensiondata/caas_2_0_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_defaultHealthMonitor.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<defaultHealthMonitors
+ xmlns="urn:didata.com:api:cloud:types" pageNumber="1" pageCount="6"
+totalCount="6" pageSize="250">
+ <defaultHealthMonitor id="01683574-d487-11e4-811f-005056806999">
+ <name>CCDEFAULT.Http</name>
+ <nodeCompatible>false</nodeCompatible>
+ <poolCompatible>true</poolCompatible>
+ </defaultHealthMonitor>
+ <defaultHealthMonitor id="0168546c-d487-11e4-811f-005056806999">
+ <name>CCDEFAULT.Https</name>
+ <nodeCompatible>false</nodeCompatible>
+ <poolCompatible>true</poolCompatible>
+ </defaultHealthMonitor>
+ <defaultHealthMonitor id="0168b83a-d487-11e4-811f-005056806999">
+ <name>CCDEFAULT.Icmp</name>
+ <nodeCompatible>true</nodeCompatible>
+ <poolCompatible>false</poolCompatible>
+ </defaultHealthMonitor>
+ <defaultHealthMonitor id="01686f4b-d487-11e4-811f-005056806999">
+ <name>CCDEFAULT.Tcp</name>
+ <nodeCompatible>false</nodeCompatible>
+ <poolCompatible>true</poolCompatible>
+ </defaultHealthMonitor>
+ <defaultHealthMonitor id="0168a2f9-d487-11e4-811f-005056806999">
+ <name>CCDEFAULT.TcpHalfOpen</name>
+ <nodeCompatible>false</nodeCompatible>
+ <poolCompatible>true</poolCompatible>
+ </defaultHealthMonitor>
+ <defaultHealthMonitor id="01688878-d487-11e4-811f-005056806999">
+ <name>CCDEFAULT.Udp</name>
+ <nodeCompatible>false</nodeCompatible>
+ <poolCompatible>true</poolCompatible>
+ </defaultHealthMonitor>
+</defaultHealthMonitors>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/libcloud/blob/89ad96c7/libcloud/test/loadbalancer/fixtures/dimensiondata/caas_2_0_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_defaultIrule.xml
----------------------------------------------------------------------
diff --git a/libcloud/test/loadbalancer/fixtures/dimensiondata/caas_2_0_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_defaultIrule.xml b/libcloud/test/loadbalancer/fixtures/dimensiondata/caas_2_0_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_defaultIrule.xml
new file mode 100644
index 0000000..d2005a3
--- /dev/null
+++ b/libcloud/test/loadbalancer/fixtures/dimensiondata/caas_2_0_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_defaultIrule.xml
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<defaultIrules
+ xmlns="urn:didata.com:api:cloud:types" pageNumber="1" pageCount="5"
+totalCount="5" pageSize="250">
+ <defaultIrule>
+ <irule id="2b20cb2c-ffdc-11e4-b010-005056806999"
+name="CCDEFAULT.HttpsRedirect"/>
+ <virtualListenerCompatibility type="PERFORMANCE_LAYER_4"
+protocol="HTTP"/>
+ </defaultIrule>
+ <defaultIrule>
+ <irule id="2b20abd9-ffdc-11e4-b010-005056806999"
+name="CCDEFAULT.IpProtocolTimers"/>
+ <virtualListenerCompatibility type="PERFORMANCE_LAYER_4"
+protocol="HTTP"/>
+ <virtualListenerCompatibility type="PERFORMANCE_LAYER_4"
+protocol="TCP"/>
+ <virtualListenerCompatibility type="STANDARD" protocol="UDP"/>
+ <virtualListenerCompatibility type="PERFORMANCE_LAYER_4"
+protocol="UDP"/>
+ <virtualListenerCompatibility type="PERFORMANCE_LAYER_4"
+protocol="ANY"/>
+ <virtualListenerCompatibility type="STANDARD" protocol="TCP"/>
+ <virtualListenerCompatibility type="STANDARD" protocol="ANY"/>
+ </defaultIrule>
+ <defaultIrule>
+ <irule id="2b20e790-ffdc-11e4-b010-005056806999"
+name="CCDEFAULT.Ips"/>
+ <virtualListenerCompatibility type="PERFORMANCE_LAYER_4"
+protocol="HTTP"/>
+ <virtualListenerCompatibility type="PERFORMANCE_LAYER_4"
+protocol="TCP"/>
+ <virtualListenerCompatibility type="STANDARD" protocol="UDP"/>
+ <virtualListenerCompatibility type="PERFORMANCE_LAYER_4"
+protocol="UDP"/>
+ <virtualListenerCompatibility type="PERFORMANCE_LAYER_4"
+protocol="ANY"/>
+ <virtualListenerCompatibility type="STANDARD" protocol="TCP"/>
+ <virtualListenerCompatibility type="STANDARD" protocol="ANY"/>
+ </defaultIrule>
+ <defaultIrule>
+ <irule id="2b210846-ffdc-11e4-b010-005056806999"
+name="CCDEFAULT.IpsHttp"/>
+ <virtualListenerCompatibility type="PERFORMANCE_LAYER_4"
+protocol="HTTP"/>
+ </defaultIrule>
+ </defaultIrules>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/libcloud/blob/89ad96c7/libcloud/test/loadbalancer/fixtures/dimensiondata/caas_2_0_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_defaultPersistenceProfile.xml
----------------------------------------------------------------------
diff --git a/libcloud/test/loadbalancer/fixtures/dimensiondata/caas_2_0_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_defaultPersistenceProfile.xml b/libcloud/test/loadbalancer/fixtures/dimensiondata/caas_2_0_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_defaultPersistenceProfile.xml
new file mode 100644
index 0000000..cd6b5a5
--- /dev/null
+++ b/libcloud/test/loadbalancer/fixtures/dimensiondata/caas_2_0_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_defaultPersistenceProfile.xml
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<defaultPersistenceProfiles
+ xmlns="urn:didata.com:api:cloud:types" pageNumber="1" pageCount="4"
+totalCount="4" pageSize="250">
+ <defaultPersistenceProfile id="a34ca024-f3db-11e4-b010-005056806999"
+fallbackCompatible="false">
+ <name>CCDEFAULT.Cookie</name>
+ <virtualListenerCompatibility type="PERFORMANCE_LAYER_4"
+protocol="HTTP"/>
+ </defaultPersistenceProfile>
+ <defaultPersistenceProfile id="a34ca25c-f3db-11e4-b010-005056806999"
+fallbackCompatible="true">
+ <name>CCDEFAULT.DestinationAddress</name>
+ <virtualListenerCompatibility type="PERFORMANCE_LAYER_4"
+protocol="HTTP"/>
+ <virtualListenerCompatibility type="PERFORMANCE_LAYER_4"
+protocol="TCP"/>
+ <virtualListenerCompatibility type="STANDARD" protocol="UDP"/>
+ <virtualListenerCompatibility type="PERFORMANCE_LAYER_4"
+protocol="UDP"/>
+ <virtualListenerCompatibility type="PERFORMANCE_LAYER_4"
+protocol="ANY"/>
+ <virtualListenerCompatibility type="STANDARD" protocol="TCP"/>
+ <virtualListenerCompatibility type="STANDARD" protocol="ANY"/>
+ </defaultPersistenceProfile>
+ <defaultPersistenceProfile id="a34ca4b7-f3db-11e4-b010-005056806999"
+fallbackCompatible="false">
+ <name>CCDEFAULT.Sip</name>
+ <virtualListenerCompatibility type="STANDARD" protocol="UDP"/>
+ <virtualListenerCompatibility type="STANDARD" protocol="TCP"/>
+ </defaultPersistenceProfile>
+ <defaultPersistenceProfile id="a34ca3f6-f3db-11e4-b010-005056806999"
+fallbackCompatible="true">
+ <name>CCDEFAULT.SourceAddress</name>
+ <virtualListenerCompatibility type="PERFORMANCE_LAYER_4"
+protocol="HTTP"/>
+ <virtualListenerCompatibility type="PERFORMANCE_LAYER_4"
+protocol="TCP"/>
+ <virtualListenerCompatibility type="STANDARD" protocol="UDP"/>
+ <virtualListenerCompatibility type="PERFORMANCE_LAYER_4"
+protocol="UDP"/>
+ <virtualListenerCompatibility type="PERFORMANCE_LAYER_4"
+protocol="ANY"/>
+ <virtualListenerCompatibility type="STANDARD" protocol="TCP"/>
+ <virtualListenerCompatibility type="STANDARD" protocol="ANY"/>
+ </defaultPersistenceProfile>
+</defaultPersistenceProfiles>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/libcloud/blob/89ad96c7/libcloud/test/loadbalancer/test_dimensiondata.py
----------------------------------------------------------------------
diff --git a/libcloud/test/loadbalancer/test_dimensiondata.py b/libcloud/test/loadbalancer/test_dimensiondata.py
index b28833b..c5929a5 100644
--- a/libcloud/test/loadbalancer/test_dimensiondata.py
+++ b/libcloud/test/loadbalancer/test_dimensiondata.py
@@ -415,6 +415,37 @@ class DimensionDataTests(unittest.TestCase):
             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):
 
@@ -526,5 +557,20 @@ class DimensionDataMockHttp(MockHttp):
             'caas_2_0_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_editPoolMember.xml')
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
+    def _caas_2_0_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_defaultHealthMonitor(self, method, url, body, headers):
+        body = self.fixtures.load(
+            'caas_2_0_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_defaultHealthMonitor.xml')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+    def _caas_2_0_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_defaultPersistenceProfile(self, method, url, body, headers):
+        body = self.fixtures.load(
+            'caas_2_0_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_defaultPersistenceProfile.xml')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+    def _caas_2_0_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_defaultIrule(self, method, url, body, headers):
+        body = self.fixtures.load(
+            'caas_2_0_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_defaultIrule.xml')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
 if __name__ == '__main__':
     sys.exit(unittest.main())


[3/3] libcloud git commit: Added better explanation and docstrings for internal classes

Posted by an...@apache.org.
Added better explanation and docstrings for internal classes

Signed-off-by: Anthony Shaw <an...@gmail.com>
Closes #653


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

Branch: refs/heads/trunk
Commit: 914c4eb3d727a273363c4e74a8a516d5394e7e85
Parents: 7b829ca
Author: Anthony Shaw <an...@gmail.com>
Authored: Mon Dec 7 08:40:31 2015 +1100
Committer: Anthony Shaw <an...@gmail.com>
Committed: Mon Dec 7 08:44:35 2015 +1100

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


http://git-wip-us.apache.org/repos/asf/libcloud/blob/914c4eb3/libcloud/common/dimensiondata.py
----------------------------------------------------------------------
diff --git a/libcloud/common/dimensiondata.py b/libcloud/common/dimensiondata.py
index a08a4f9..2cc2a6c 100644
--- a/libcloud/common/dimensiondata.py
+++ b/libcloud/common/dimensiondata.py
@@ -435,13 +435,13 @@ class DimensionDataVlan(object):
         Initialize an instance of ``DimensionDataVlan``
 
         :param id: The ID of the VLAN
-        :type  id: ``string``
+        :type  id: ``str``
 
         :param name: The name of the VLAN
-        :type  name: ``string``
+        :type  name: ``str``
 
         :param description: Plan text description of the VLAN
-        :type  description: ``string``
+        :type  description: ``str``
 
         :param location: The location (data center) of the VLAN
         :type  location: ``NodeLocation``
@@ -454,11 +454,11 @@ class DimensionDataVlan(object):
 
         :param private_ipv4_range_address: The host address of the VLAN
                                             IP space
-        :type  private_ipv4_range_address: ``string``
+        :type  private_ipv4_range_address: ``str``
 
         :param private_ipv4_range_address: The size (e.g. '24') of the VLAN
                                             as a CIDR range size
-        :type  private_ipv4_range_address: ``string``
+        :type  private_ipv4_range_address: ``str``
         """
         self.id = str(id)
         self.name = name
@@ -483,6 +483,33 @@ class DimensionDataPool(object):
 
     def __init__(self, id, name, description, status, load_balance_method,
                  health_monitor_id, service_down_action, slow_ramp_time):
+        """
+        Initialize an instance of ``DimensionDataPool``
+
+        :param id: The ID of the pool
+        :type  id: ``str``
+
+        :param name: The name of the pool
+        :type  name: ``str``
+
+        :param description: Plan text description of the pool
+        :type  description: ``str``
+
+        :param status: The status of the pool
+        :type  status: :class:`DimensionDataStatus`
+
+        :param load_balance_method: The load balancer method
+        :type  load_balance_method: ``str``
+
+        :param health_monitor_id: The ID of the health monitor
+        :type  health_monitor_id: ``str``
+
+        :param service_down_action: Action to take when pool is down
+        :type  service_down_action: ``str``
+
+        :param slow_ramp_time: The ramp-up time for service recovery
+        :type  slow_ramp_time: ``int``
+        """
         self.id = str(id)
         self.name = name
         self.description = description
@@ -505,6 +532,27 @@ class DimensionDataPoolMember(object):
     """
 
     def __init__(self, id, name, status, ip, port, node_id):
+        """
+        Initialize an instance of ``DimensionDataPoolMember``
+
+        :param id: The ID of the pool member
+        :type  id: ``str``
+
+        :param name: The name of the pool member
+        :type  name: ``str``
+
+        :param status: The status of the pool
+        :type  status: :class:`DimensionDataStatus`
+
+        :param ip: The IP of the pool member
+        :type  ip: ``str``
+
+        :param port: The port of the pool member
+        :type  port: ``int``
+
+        :param node_id: The ID of the associated node
+        :type  node_id: ``str``
+        """
         self.id = str(id)
         self.name = name
         self.status = status
@@ -523,6 +571,27 @@ class DimensionDataPoolMember(object):
 class DimensionDataVIPNode(object):
     def __init__(self, id, name, status, ip, connection_limit='10000',
                  connection_rate_limit='10000'):
+        """
+        Initialize an instance of :class:`DimensionDataVIPNode`
+
+        :param id: The ID of the node
+        :type  id: ``str``
+
+        :param name: The name of the node
+        :type  name: ``str``
+
+        :param status: The status of the node
+        :type  status: :class:`DimensionDataStatus`
+
+        :param ip: The IP of the node
+        :type  ip: ``str``
+
+        :param connection_limit: The total connection limit for the node
+        :type  connection_limit: ``int``
+
+        :param connection_rate_limit: The rate limit for the node
+        :type  connection_rate_limit: ``int``
+        """
         self.id = str(id)
         self.name = name
         self.status = status
@@ -543,6 +612,21 @@ class DimensionDataVirtualListener(object):
     """
 
     def __init__(self, id, name, status, ip):
+        """
+        Initialize an instance of :class:`DimensionDataVirtualListener`
+
+        :param id: The ID of the listener
+        :type  id: ``str``
+
+        :param name: The name of the listener
+        :type  name: ``str``
+
+        :param status: The status of the listener
+        :type  status: :class:`DimensionDataStatus`
+
+        :param ip: The IP of the listener
+        :type  ip: ``str``
+        """
         self.id = str(id)
         self.name = name
         self.status = status
@@ -560,6 +644,21 @@ class DimensionDataDefaultHealthMonitor(object):
     A default health monitor for a VIP (node, pool or listener)
     """
     def __init__(self, id, name, node_compatible, pool_compatible):
+        """
+        Initialize an instance of :class:`DimensionDataDefaultHealthMonitor`
+
+        :param id: The ID of the monitor
+        :type  id: ``str``
+
+        :param name: The name of the monitor
+        :type  name: ``str``
+
+        :param node_compatible: Is a monitor capable of monitoring nodes
+        :type  node_compatible: ``bool``
+
+        :param pool_compatible: Is a monitor capable of monitoring pools
+        :type  pool_compatible: ``bool``
+        """
         self.id = id
         self.name = name
         self.node_compatible = node_compatible
@@ -578,6 +677,22 @@ class DimensionDataPersistenceProfile(object):
     Fallback Persistence Profile.
     """
     def __init__(self, id, name, compatible_listeners, fallback_compatible):
+        """
+        Initialize an instance of :class:`DimensionDataPersistenceProfile`
+
+        :param id: The ID of the profile
+        :type  id: ``str``
+
+        :param name: The name of the profile
+        :type  name: ``str``
+
+        :param compatible_listeners: List of compatible Virtual Listener types
+        :type  compatible_listeners: ``list`` of
+            :class:`DimensionDataVirtualListenerCompatibility`
+
+        :param fallback_compatible: Is capable as a fallback profile
+        :type  fallback_compatible: ``bool``
+        """
         self.id = id
         self.name = name
         self.compatible_listeners = compatible_listeners
@@ -593,6 +708,19 @@ class DimensionDataDefaultiRule(object):
     A default iRule for a network domain, can be applied to a listener
     """
     def __init__(self, id, name, compatible_listeners):
+        """
+        Initialize an instance of :class:`DimensionDataDefaultiRule`
+
+        :param id: The ID of the iRule
+        :type  id: ``str``
+
+        :param name: The name of the iRule
+        :type  name: ``str``
+
+        :param compatible_listeners: List of compatible Virtual Listener types
+        :type  compatible_listeners: ``list`` of
+            :class:`DimensionDataVirtualListenerCompatibility`
+        """
         self.id = id
         self.name = name
         self.compatible_listeners = compatible_listeners
@@ -604,7 +732,9 @@ class DimensionDataDefaultiRule(object):
 
 class DimensionDataVirtualListenerCompatibility(object):
     """
-    A compatibility preference for a persistence profile
+    A compatibility preference for a persistence profile or iRule
+    specifies which virtual listener types this profile or iRule can be
+    applied to.
     """
     def __init__(self, type, protocol):
         self.type = type


[2/3] libcloud git commit: Flake, i ran the tests locally! i need to apply the same profile

Posted by an...@apache.org.
Flake, i ran the tests locally! i need to apply the same profile

Signed-off-by: Anthony Shaw <an...@gmail.com>


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

Branch: refs/heads/trunk
Commit: 7b829cac87d07348e41c974e6de2ca970aeeef06
Parents: 89ad96c
Author: Anthony Shaw <an...@gmail.com>
Authored: Fri Dec 4 16:28:51 2015 +1100
Committer: Anthony Shaw <an...@gmail.com>
Committed: Mon Dec 7 08:44:25 2015 +1100

----------------------------------------------------------------------
 libcloud/loadbalancer/drivers/dimensiondata.py | 12 ++++--------
 1 file changed, 4 insertions(+), 8 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/libcloud/blob/7b829cac/libcloud/loadbalancer/drivers/dimensiondata.py
----------------------------------------------------------------------
diff --git a/libcloud/loadbalancer/drivers/dimensiondata.py b/libcloud/loadbalancer/drivers/dimensiondata.py
index 462a2b0..337997d 100644
--- a/libcloud/loadbalancer/drivers/dimensiondata.py
+++ b/libcloud/loadbalancer/drivers/dimensiondata.py
@@ -950,9 +950,7 @@ class DimensionDataLBDriver(Driver):
             compatible.append(
                 DimensionDataVirtualListenerCompatibility(
                     type=match_element.get('type'),
-                    protocol=match_element.get('protocol', None)
-                )
-                )
+                    protocol=match_element.get('protocol', None)))
         irule_element = element.find(fixxpath('irule', TYPES_URN))
         return DimensionDataDefaultiRule(
             id=irule_element.get('id'),
@@ -976,14 +974,12 @@ class DimensionDataLBDriver(Driver):
             compatible.append(
                 DimensionDataVirtualListenerCompatibility(
                     type=match_element.get('type'),
-                    protocol=match_element.get('protocol', None)
-                )
-                )
+                    protocol=match_element.get('protocol', None)))
 
         return DimensionDataPersistenceProfile(
             id=element.get('id'),
-            fallback_compatible=bool(element.get('fallbackCompatible')
-                                     == "true"),
+            fallback_compatible=bool(
+                element.get('fallbackCompatible') == "true"),
             name=findtext(element, 'name', TYPES_URN),
             compatible_listeners=compatible
         )