139 lines
4.7 KiB
Python
139 lines
4.7 KiB
Python
# 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.common.brightbox import BrightboxConnection
|
|
from libcloud.loadbalancer.base import Driver, Algorithm, Member
|
|
from libcloud.loadbalancer.base import LoadBalancer
|
|
from libcloud.loadbalancer.types import State
|
|
from libcloud.utils.misc import reverse_dict
|
|
|
|
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('/%s/load_balancers/%s' %
|
|
(API_VERSION, balancer.id),
|
|
method='DELETE')
|
|
|
|
return response.status == httplib.ACCEPTED
|
|
|
|
def get_balancer(self, balancer_id):
|
|
data = self.connection.request(
|
|
'/%s/load_balancers/%s' % (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 = '/%s/load_balancers/%s/add_nodes' % (API_VERSION, balancer.id)
|
|
|
|
self._post(path, {'nodes': [self._member_to_node(member)]})
|
|
|
|
return member
|
|
|
|
def balancer_detach_member(self, balancer, member):
|
|
path = '/%s/load_balancers/%s/remove_nodes' % (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 = '/%s/load_balancers/%s' % (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
|