libcloud-notifications mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From anthonys...@apache.org
Subject [2/6] libcloud git commit: - AWS ALB driver with basic get methods
Date Thu, 10 Nov 2016 01:04:09 GMT
- AWS ALB driver with basic get methods


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

Branch: refs/heads/trunk
Commit: be673ee01dde7ede7772f3a30388aaccbc44e184
Parents: a58a6e5
Author: Anton Kozyrev <anton.kozyrev@gmail.com>
Authored: Fri Oct 28 16:58:58 2016 +0300
Committer: Anthony Shaw <anthonyshaw@apache.org>
Committed: Thu Nov 10 11:31:25 2016 +1100

----------------------------------------------------------------------
 libcloud/loadbalancer/drivers/alb.py | 295 ++++++++++++++++++++++++++++++
 libcloud/loadbalancer/providers.py   |   2 +
 libcloud/loadbalancer/types.py       |   1 +
 3 files changed, 298 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/libcloud/blob/be673ee0/libcloud/loadbalancer/drivers/alb.py
----------------------------------------------------------------------
diff --git a/libcloud/loadbalancer/drivers/alb.py b/libcloud/loadbalancer/drivers/alb.py
new file mode 100644
index 0000000..603bd7c
--- /dev/null
+++ b/libcloud/loadbalancer/drivers/alb.py
@@ -0,0 +1,295 @@
+# 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.
+
+__all__ = [
+    'ApplicationLBDriver'
+]
+
+from libcloud.utils.py3 import httplib
+from libcloud.utils.xml import findtext, findall
+from libcloud.loadbalancer.types import State
+from libcloud.loadbalancer.base import Driver, LoadBalancer, Member
+from libcloud.common.aws import AWSGenericResponse, SignedAWSConnection
+
+
+VERSION = '2015-12-01'
+HOST = 'elasticloadbalancing.%s.amazonaws.com'
+ROOT = '/%s/' % (VERSION)
+NS = 'http://elasticloadbalancing.amazonaws.com/doc/%s/' % (VERSION, )
+
+
+class ALBResponse(AWSGenericResponse):
+    """
+    Amazon ALB response class.
+    """
+    namespace = NS
+    exceptions = {}
+    xpath = 'Error'
+
+
+class ALBConnection(SignedAWSConnection):
+    version = VERSION
+    host = HOST
+    responseCls = ALBResponse
+    service_name = 'elasticloadbalancing'
+
+
+class ApplicationLBDriver(Driver):
+    name = 'Amazon Application Load Balancing'
+    website = 'http://aws.amazon.com/elasticloadbalancing/'
+    connectionCls = ALBConnection
+    signature_version = '4'
+
+    def __init__(self, access_id, secret, region, token=None):
+        self.token = token
+        super(ApplicationLBDriver, self).__init__(access_id, secret, token=token)
+        self.region = region
+        self.region_name = region
+        self.connection.host = HOST % (region)
+
+    def list_protocols(self):
+        return ['http', 'https']
+
+    def list_balancers(self):
+        params = {'Action': 'DescribeLoadBalancers'}
+        data = self.connection.request(ROOT, params=params).object
+        return self._to_balancers(data)
+
+    def balancer_list_members(self, balancer):
+        return balancer._members
+
+    def get_balancer(self, balancer_id):
+        params = {
+            'Action': 'DescribeLoadBalancers',
+            'LoadBalancerNames.member.1': balancer_id
+        }
+        data = self.connection.request(ROOT, params=params).object
+        return self._to_balancers(data)[0]
+
+    def ex_balancer_list_listeners(self, balancer):
+        return balancer.extra.get('listeners', [])
+
+    def _to_listeners(self, data):
+        xpath = 'DescribeListenersResult/Listeners/member'
+        return [self._to_listener(el) for el in findall(element=data, xpath=xpath, namespace=NS)]
+
+    def _to_listener(self, el):
+        listener_arn = findtext(element=el, xpath='ListenerArn', namespace=NS)
+        listener = {
+            'id': listener_arn,
+            'protocol': findtext(element=el, xpath='Protocol', namespace=NS),
+            'port': findtext(element=el, xpath='Port', namespace=NS),
+            'rules': self._ex_get_rules_for_listener(listener_arn)
+        }
+        return listener
+
+    def _to_targets(self, data):
+        xpath = 'DefaultActions/member'
+        return [self._to_target(el) for el in findall(element=data, xpath=xpath, namespace=NS)]
+
+    def _to_target(self, el):
+        return findtext(element=el, xpath='DefaultActions/member/TargetGroupArn', namespace=NS)
+
+    def _to_balancer(self, el):
+        name = findtext(element=el, xpath='LoadBalancerName', namespace=NS)
+        id = findtext(element=el, xpath='LoadBalancerArn', namespace=NS)
+        dns_name = findtext(el, xpath='DNSName', namespace=NS)
+
+        balancer = LoadBalancer(
+            id=id,
+            name=name,
+            state=State.UNKNOWN,
+            ip=dns_name,
+            port=None,
+            driver=self.connection.driver
+        )
+
+        extra = {
+            'listeners': self._ex_get_balancer_listeners(balancer),
+            'target_groups': self._ex_get_balancer_target_groups(balancer),
+            'tags': self._ex_get_balancer_tags(balancer)
+        }
+        balancer.extra = extra
+        balancer.port = extra['listeners'][0]['port'] if len(extra['listeners']) > 0 else
None
+        balancer._members = self._ex_get_balancer_memebers(balancer)
+
+        return balancer
+
+    def _to_balancers(self, data):
+        xpath = 'DescribeLoadBalancersResult/LoadBalancers/member'
+        return [self._to_balancer(el)
+                for el in findall(element=data, xpath=xpath, namespace=NS)]
+
+    def _to_tags(self, data):
+        """
+        return tags dict
+        """
+        tags = {}
+        xpath = 'DescribeTagsResult/TagDescriptions/member/Tags/member'
+
+        for el in findall(element=data, xpath=xpath, namespace=NS):
+            key = findtext(element=el, xpath='Key', namespace=NS)
+            value = findtext(element=el, xpath='Value', namespace=NS)
+            if key:
+                tags[key] = value
+
+        return tags
+
+    def _to_rule(self, el):
+        def __to_bool(val):
+            return val.lower() in ("yes", "true", "t", "1")
+
+        id = findtext(element=el, xpath='RuleArn', namespace=NS)
+        is_default = findtext(element=el, xpath='IsDefault', namespace=NS)
+        priority = findtext(element=el, xpath='Priority', namespace=NS)
+        target_group = findtext(element=el, xpath='Actions/member/TargetGroupArn', namespace=NS)
+        conditions = {}
+
+        for cond_member in findall(element=el, xpath='Conditions/member', namespace=NS):
+            field = findtext(element=cond_member, xpath='Field', namespace=NS)
+            conditions[field] = []
+            for value_member in findall(element=cond_member, xpath='Values/member', namespace=NS):
+                conditions[field].append(value_member.text)
+
+        rule = {
+            'id': id,
+            'is_default': __to_bool(is_default),
+            'priority': priority,
+            'target_group': target_group,
+            'conditions': conditions
+        }
+
+        return rule
+
+    def _to_rules(self, data):
+        xpath = 'DescribeRulesResult/Rules/member'
+        return [self._to_rule(el)
+                for el in findall(element=data, xpath=xpath, namespace=NS)]
+
+    def _to_target_groups(self, data):
+        xpath = 'DescribeTargetGroupsResult/TargetGroups/member'
+        return [self._to_target_group(el)
+                for el in findall(element=data, xpath=xpath, namespace=NS)]
+
+    def _to_target_group(self, el):
+        target_group_arn = findtext(element=el, xpath='TargetGroupArn', namespace=NS)
+        name = findtext(element=el, xpath='TargetGroupName', namespace=NS)
+        members = self._ex_get_target_group_members(target_group_arn)
+
+        return {'id': target_group_arn, 'name': name, 'members': members}
+
+    def _to_target_group_members(self, data):
+        xpath = 'DescribeTargetHealthResult/TargetHealthDescriptions/member'
+        return [self._to_target_group_member(el)
+                for el in findall(element=data, xpath=xpath, namespace=NS)]
+
+    def _to_target_group_member(self, el):
+        id = findtext(element=el, xpath='Target/Id', namespace=NS)
+        port = findtext(element=el, xpath='Target/Port', namespace=NS)
+        health = findtext(element=el, xpath='TargetHealth/State', namespace=NS)
+
+        return {'id': id, 'port': port, 'health': health}
+
+    def _ex_get_balancer_memebers(self, balancer):
+        balancer_members = []
+        for tg in balancer.extra['target_groups']:
+            for tg_member in tg['members']:
+                new_member = Member(
+                    tg_member['id'],
+                    None,
+                    tg_member['port'],
+                    balancer=balancer,
+                    extra={
+                        'health': tg_member['health'],
+                        'target_group': tg['name']
+                    }
+                )
+                balancer_members.append(new_member)
+
+        return balancer_members
+
+    def _ex_get_target_group_members(self, target_group_arn):
+        """
+        Return a list of target group member dicts.
+
+        :rtype: ``list`` of ``dict``
+        """
+        params = {
+            'Action': 'DescribeTargetHealth',
+            'TargetGroupArn': target_group_arn
+        }
+
+        data = self.connection.request(ROOT, params=params).object
+        return self._to_target_group_members(data)
+
+    def _ex_get_balancer_target_groups(self, balancer):
+        """
+        Return a list of load balancer target groups with members.
+
+        :rtype: ``list`` of ``dict``
+        """
+        params = {
+            'Action': 'DescribeTargetGroups',
+            'LoadBalancerArn': balancer.id
+        }
+
+        data = self.connection.request(ROOT, params=params).object
+        return self._to_target_groups(data)
+
+    def _ex_get_balancer_listeners(self, balancer):
+        """
+        Return a list of load balancer listeners dicts.
+
+        :rtype: ``list`` of ``dict``
+        """
+        params = {
+            'Action': 'DescribeListeners',
+            'LoadBalancerArn': balancer.id
+        }
+
+        data = self.connection.request(ROOT, params=params).object
+        return self._to_listeners(data)
+
+    def _ex_get_rules_for_listener(self, listener_arn):
+        """
+        Return a list of listeners rule dicts.
+
+        :rtype: ``list`` of ``dict``
+        """
+        params = {
+            'Action': 'DescribeRules',
+            'ListenerArn': listener_arn
+        }
+
+        data = self.connection.request(ROOT, params=params).object
+        return self._to_rules(data)
+
+    def _ex_connection_class_kwargs(self):
+        kwargs = super(ApplicationLBDriver, self)._ex_connection_class_kwargs()
+        if hasattr(self, 'token') and self.token is not None:
+            kwargs['token'] = self.token
+            kwargs['signature_version'] = '4'
+        else:
+            kwargs['signature_version'] = self.signature_version
+
+        return kwargs
+
+    def _ex_get_balancer_tags(self, balancer):
+        params = {
+            'Action': 'DescribeTags',
+            'ResourceArns.member.1': balancer.id
+        }
+        data = self.connection.request(ROOT, params=params).object
+        return self._to_tags(data)

http://git-wip-us.apache.org/repos/asf/libcloud/blob/be673ee0/libcloud/loadbalancer/providers.py
----------------------------------------------------------------------
diff --git a/libcloud/loadbalancer/providers.py b/libcloud/loadbalancer/providers.py
index 49a0f3a..a778304 100644
--- a/libcloud/loadbalancer/providers.py
+++ b/libcloud/loadbalancer/providers.py
@@ -35,6 +35,8 @@ DRIVERS = {
     ('libcloud.loadbalancer.drivers.brightbox', 'BrightboxLBDriver'),
     Provider.ELB:
     ('libcloud.loadbalancer.drivers.elb', 'ElasticLBDriver'),
+    Provider.ALB:
+        ('libcloud.loadbalancer.drivers.alb', 'ApplicationLBDriver'),
     Provider.CLOUDSTACK:
     ('libcloud.loadbalancer.drivers.cloudstack', 'CloudStackLBDriver'),
     Provider.GCE:

http://git-wip-us.apache.org/repos/asf/libcloud/blob/be673ee0/libcloud/loadbalancer/types.py
----------------------------------------------------------------------
diff --git a/libcloud/loadbalancer/types.py b/libcloud/loadbalancer/types.py
index 391fdf7..5752622 100644
--- a/libcloud/loadbalancer/types.py
+++ b/libcloud/loadbalancer/types.py
@@ -42,6 +42,7 @@ class Provider(object):
 
     :cvar ALIYUN_SLB: Aliyun SLB loadbalancer driver
     """
+    ALB = 'alb'
     ALIYUN_SLB = 'aliyun_slb'
     BRIGHTBOX = 'brightbox'
     CLOUDSTACK = 'cloudstack'


Mime
View raw message