Repository: libcloud Updated Branches: refs/heads/trunk d12def1d8 -> a26da95ef
Support GCE LB session affinity Add support for sessionAffinity to the GCE Load Balancer driver. sessionAffinity has the effect of causing clients to "stick" to a particular backend server. Also, trivial documentation fixes: * resolve ambiguous type specification in create_balancer * fix typo in development doc Closes #341 Signed-off-by: Tomaz Muraus <[email protected]> Project: http://git-wip-us.apache.org/repos/asf/libcloud/repo Commit: http://git-wip-us.apache.org/repos/asf/libcloud/commit/a26da95e Tree: http://git-wip-us.apache.org/repos/asf/libcloud/tree/a26da95e Diff: http://git-wip-us.apache.org/repos/asf/libcloud/diff/a26da95e Branch: refs/heads/trunk Commit: a26da95ef1d532ba2379eafc707c358922d462e3 Parents: d12def1 Author: Lee Verberne <[email protected]> Authored: Thu Jul 10 13:31:34 2014 -0700 Committer: Tomaz Muraus <[email protected]> Committed: Sun Jul 20 15:45:30 2014 +0200 ---------------------------------------------------------------------- CHANGES.rst | 9 +++++++++ docs/development.rst | 4 ++-- libcloud/compute/drivers/gce.py | 9 ++++++++- libcloud/loadbalancer/drivers/gce.py | 13 ++++++++++--- ...s-central1_targetPools_lctargetpool_sticky.json | 9 +++++++++ libcloud/test/compute/test_gce.py | 17 +++++++++++++++++ 6 files changed, 55 insertions(+), 6 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/libcloud/blob/a26da95e/CHANGES.rst ---------------------------------------------------------------------- diff --git a/CHANGES.rst b/CHANGES.rst index 5ffdb69..17999cc 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -16,6 +16,15 @@ Compute (LIBCLOUD-594, GITHUB-337) [Atsushi Sasaki] + +Loadbalancer +~~~~~~~~~~~~ + +- Allow user to specify session affinity algorithm in the GCE driver by passing + ``ex_session_affinity`` argument to the ``create_balancer`` method. + (LIBCLOUD-595, GITHUB-341) + [Lee Verberne, Eric Johnson] + Changes with Apache Libcloud 0.15.1 ----------------------------------- http://git-wip-us.apache.org/repos/asf/libcloud/blob/a26da95e/docs/development.rst ---------------------------------------------------------------------- diff --git a/docs/development.rst b/docs/development.rst index 3bd9ea4..8899df9 100644 --- a/docs/development.rst +++ b/docs/development.rst @@ -212,8 +212,8 @@ Bad (please avoid): description = kwargs.get('description', None) public_ips = kwargs.get('public_ips', None) -5. When returning a dictionary, document it's structure -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +5. When returning a dictionary, document its structure +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Dynamic nature of Python can be very nice and useful, but if (ab)use it in a wrong way it can also make it hard for the API consumer to understand what is http://git-wip-us.apache.org/repos/asf/libcloud/blob/a26da95e/libcloud/compute/drivers/gce.py ---------------------------------------------------------------------- diff --git a/libcloud/compute/drivers/gce.py b/libcloud/compute/drivers/gce.py index 28bcb48..62164fd 100644 --- a/libcloud/compute/drivers/gce.py +++ b/libcloud/compute/drivers/gce.py @@ -1350,7 +1350,7 @@ class GCENodeDriver(NodeDriver): return node_list def ex_create_targetpool(self, name, region=None, healthchecks=None, - nodes=None): + nodes=None, session_affinity=None): """ Create a target pool. @@ -1367,6 +1367,10 @@ class GCENodeDriver(NodeDriver): :keyword nodes: Optional list of nodes to attach to the pool :type nodes: ``list`` of ``str`` or :class:`Node` + :keyword session_affinity: Optional algorithm to use for session + affinity. + :type session_affinity: ``str`` + :return: Target Pool object :rtype: :class:`GCETargetPool` """ @@ -1391,6 +1395,8 @@ class GCENodeDriver(NodeDriver): else: node_list = [n.extra['selfLink'] for n in nodes] targetpool_data['instances'] = node_list + if session_affinity: + targetpool_data['sessionAffinity'] = session_affinity request = '/regions/%s/targetPools' % (region.name) @@ -3316,6 +3322,7 @@ class GCENodeDriver(NodeDriver): extra = {} extra['selfLink'] = targetpool.get('selfLink') extra['description'] = targetpool.get('description') + extra['sessionAffinity'] = targetpool.get('sessionAffinity') region = self.ex_get_region(targetpool['region']) healthcheck_list = [self.ex_get_healthcheck(h.split('/')[-1]) for h in targetpool.get('healthChecks', [])] http://git-wip-us.apache.org/repos/asf/libcloud/blob/a26da95e/libcloud/loadbalancer/drivers/gce.py ---------------------------------------------------------------------- diff --git a/libcloud/loadbalancer/drivers/gce.py b/libcloud/loadbalancer/drivers/gce.py index 09a32fd..e1fa299 100644 --- a/libcloud/loadbalancer/drivers/gce.py +++ b/libcloud/loadbalancer/drivers/gce.py @@ -89,7 +89,8 @@ class GCELBDriver(Driver): return balancers def create_balancer(self, name, port, protocol, algorithm, members, - ex_region=None, ex_healthchecks=None, ex_address=None): + ex_region=None, ex_healthchecks=None, ex_address=None, + ex_session_affinity=None): """ Create a new load balancer instance. @@ -126,12 +127,18 @@ class GCELBDriver(Driver): :keyword ex_healthchecks: Optional list of healthcheck objects or names to add to the load balancer. :type ex_healthchecks: ``list`` of :class:`GCEHealthCheck` or - ``str`` + ``list`` of ``str`` :keyword ex_address: Optional static address object to be assigned to the load balancer. :type ex_address: C{GCEAddress} + :keyword ex_session_affinity: Optional algorithm to use for session + affinity. This will modify the hashing + algorithm such that a client will tend + to stick to a particular Member. + :type ex_session_affinity: ``str`` + :return: LoadBalancer object :rtype: :class:`LoadBalancer` """ @@ -154,7 +161,7 @@ class GCELBDriver(Driver): tp_name = '%s-tp' % name targetpool = self.gce.ex_create_targetpool( tp_name, region=ex_region, healthchecks=ex_healthchecks, - nodes=node_list) + nodes=node_list, session_affinity=ex_session_affinity) # Create the Forwarding rule, but if it fails, delete the target pool. try: http://git-wip-us.apache.org/repos/asf/libcloud/blob/a26da95e/libcloud/test/compute/fixtures/gce/regions_us-central1_targetPools_lctargetpool_sticky.json ---------------------------------------------------------------------- diff --git a/libcloud/test/compute/fixtures/gce/regions_us-central1_targetPools_lctargetpool_sticky.json b/libcloud/test/compute/fixtures/gce/regions_us-central1_targetPools_lctargetpool_sticky.json new file mode 100644 index 0000000..caf3f87 --- /dev/null +++ b/libcloud/test/compute/fixtures/gce/regions_us-central1_targetPools_lctargetpool_sticky.json @@ -0,0 +1,9 @@ +{ + "creationTimestamp": "2014-07-11T15:52:43.720-07:00", + "id": "13598380121688918358", + "kind": "compute#targetPool", + "name": "lctargetpool-sticky", + "region": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1", + "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/regions/us-central1/targetPools/lctargetpool-sticky", + "sessionAffinity": "CLIENT_IP_PROTO" +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/libcloud/blob/a26da95e/libcloud/test/compute/test_gce.py ---------------------------------------------------------------------- diff --git a/libcloud/test/compute/test_gce.py b/libcloud/test/compute/test_gce.py index faf6303..963675b 100644 --- a/libcloud/test/compute/test_gce.py +++ b/libcloud/test/compute/test_gce.py @@ -327,6 +327,17 @@ class GCENodeDriverTest(LibcloudTestCase, TestCaseMixin): self.assertEqual(len(targetpool.nodes), len(nodes)) self.assertEqual(targetpool.region.name, region) + def test_ex_create_targetpool_session_affinity(self): + targetpool_name = 'lctargetpool-sticky' + region = 'us-central1' + session_affinity = 'CLIENT_IP_PROTO' + targetpool = self.driver.ex_create_targetpool( + targetpool_name, region=region, + session_affinity=session_affinity) + self.assertEqual(targetpool.name, targetpool_name) + self.assertEqual(targetpool.extra.get('sessionAffinity'), + session_affinity) + def test_ex_create_volume_snapshot(self): snapshot_name = 'lcsnapshot' volume = self.driver.ex_get_volume('lcdisk') @@ -1038,6 +1049,12 @@ class GCEMockHttp(MockHttpTestCase): 'regions_us-central1_targetPools_lctargetpool.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) + def _regions_us_central1_targetPools_lctargetpool_sticky(self, method, url, + body, headers): + body = self.fixtures.load( + 'regions_us-central1_targetPools_lctargetpool_sticky.json') + return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) + def _regions_us_central1_targetPools_libcloud_lb_demo_lb_tp( self, method, url, body, headers): body = self.fixtures.load(
