| # 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. |
| |
| |
| from libcloud.utils.py3 import httplib |
| from libcloud.utils.misc import reverse_dict |
| from libcloud.common.brightbox import BrightboxConnection |
| from libcloud.loadbalancer.base import Driver, Member, Algorithm, LoadBalancer |
| from libcloud.loadbalancer.types import State |
| |
| API_VERSION = "1.0" |
| |
| |
| class BrightboxLBDriver(Driver): |
| connectionCls = BrightboxConnection |
| |
| name = "Brightbox" |
| website = "http://www.brightbox.co.uk/" |
| |
| LB_STATE_MAP = { |
| "creating": State.PENDING, |
| "active": State.RUNNING, |
| "deleting": State.UNKNOWN, |
| "deleted": State.UNKNOWN, |
| "failing": State.UNKNOWN, |
| "failed": State.UNKNOWN, |
| } |
| |
| _VALUE_TO_ALGORITHM_MAP = { |
| "round-robin": Algorithm.ROUND_ROBIN, |
| "least-connections": Algorithm.LEAST_CONNECTIONS, |
| } |
| |
| _ALGORITHM_TO_VALUE_MAP = reverse_dict(_VALUE_TO_ALGORITHM_MAP) |
| |
| def list_protocols(self): |
| return ["tcp", "http"] |
| |
| def list_balancers(self): |
| data = self.connection.request("/%s/load_balancers" % API_VERSION).object |
| |
| return list(map(self._to_balancer, data)) |
| |
| def create_balancer(self, name, port, protocol, algorithm, members): |
| response = self._post( |
| "/%s/load_balancers" % API_VERSION, |
| { |
| "name": name, |
| "nodes": list(map(self._member_to_node, members)), |
| "policy": self._algorithm_to_value(algorithm), |
| "listeners": [{"in": port, "out": port, "protocol": protocol}], |
| "healthcheck": {"type": protocol, "port": port}, |
| }, |
| ) |
| |
| return self._to_balancer(response.object) |
| |
| def destroy_balancer(self, balancer): |
| response = self.connection.request( |
| "/{}/load_balancers/{}".format(API_VERSION, balancer.id), method="DELETE" |
| ) |
| |
| return response.status == httplib.ACCEPTED |
| |
| def get_balancer(self, balancer_id): |
| data = self.connection.request( |
| "/{}/load_balancers/{}".format(API_VERSION, balancer_id) |
| ).object |
| return self._to_balancer(data) |
| |
| def balancer_attach_compute_node(self, balancer, node): |
| return self.balancer_attach_member(balancer, node) |
| |
| def balancer_attach_member(self, balancer, member): |
| path = "/{}/load_balancers/{}/add_nodes".format(API_VERSION, balancer.id) |
| |
| self._post(path, {"nodes": [self._member_to_node(member)]}) |
| |
| return member |
| |
| def balancer_detach_member(self, balancer, member): |
| path = "/{}/load_balancers/{}/remove_nodes".format(API_VERSION, balancer.id) |
| |
| response = self._post(path, {"nodes": [self._member_to_node(member)]}) |
| |
| return response.status == httplib.ACCEPTED |
| |
| def balancer_list_members(self, balancer): |
| path = "/{}/load_balancers/{}".format(API_VERSION, balancer.id) |
| |
| data = self.connection.request(path).object |
| |
| def func(data): |
| return self._node_to_member(data, balancer) |
| |
| return list(map(func, data["nodes"])) |
| |
| def _post(self, path, data={}): |
| headers = {"Content-Type": "application/json"} |
| |
| return self.connection.request(path, data=data, headers=headers, method="POST") |
| |
| def _to_balancer(self, data): |
| return LoadBalancer( |
| id=data["id"], |
| name=data["name"], |
| state=self.LB_STATE_MAP.get(data["status"], State.UNKNOWN), |
| ip=self._public_ip(data), |
| port=data["listeners"][0]["in"], |
| driver=self.connection.driver, |
| ) |
| |
| def _member_to_node(self, member): |
| return {"node": member.id} |
| |
| def _node_to_member(self, data, balancer): |
| return Member(id=data["id"], ip=None, port=None, balancer=balancer) |
| |
| def _public_ip(self, data): |
| if len(data["cloud_ips"]) > 0: |
| ip = data["cloud_ips"][0]["public_ip"] |
| else: |
| ip = None |
| |
| return ip |