Source code for libcloud.loadbalancer.drivers.cloudstack

# 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.common.cloudstack import CloudStackDriverMixIn
from libcloud.loadbalancer.base import LoadBalancer, Member, Driver, Algorithm
from libcloud.loadbalancer.base import DEFAULT_ALGORITHM
from libcloud.loadbalancer.types import Provider
from libcloud.loadbalancer.types import State
from libcloud.utils.misc import reverse_dict


[docs]class CloudStackLBDriver(CloudStackDriverMixIn, Driver): """Driver for CloudStack load balancers.""" api_name = 'cloudstack_lb' name = 'CloudStack' website = 'http://cloudstack.org/' type = Provider.CLOUDSTACK _VALUE_TO_ALGORITHM_MAP = { 'roundrobin': Algorithm.ROUND_ROBIN, 'leastconn': Algorithm.LEAST_CONNECTIONS } _ALGORITHM_TO_VALUE_MAP = reverse_dict(_VALUE_TO_ALGORITHM_MAP) LB_STATE_MAP = { 'Active': State.RUNNING, } def __init__(self, key, secret=None, secure=True, host=None, path=None, port=None, *args, **kwargs): """ @inherits: :class:`Driver.__init__` """ host = host if host else self.host path = path if path else self.path if path is not None: self.path = path if host is not None: self.host = host if (self.type == Provider.CLOUDSTACK) and (not host or not path): raise Exception('When instantiating CloudStack driver directly ' + 'you also need to provide host and path argument') super(CloudStackLBDriver, self).__init__(key=key, secret=secret, secure=secure, host=host, port=port)
[docs] def list_protocols(self): """ We don't actually have any protocol awareness beyond TCP. :rtype: ``list`` of ``str`` """ return ['tcp']
[docs] def list_balancers(self): balancers = self._sync_request(command='listLoadBalancerRules', method='GET') balancers = balancers.get('loadbalancerrule', []) return [self._to_balancer(balancer) for balancer in balancers]
[docs] def get_balancer(self, balancer_id): balancer = self._sync_request(command='listLoadBalancerRules', params={'id': balancer_id}, method='GET') balancer = balancer.get('loadbalancerrule', []) if not balancer: raise Exception("no such load balancer: " + str(balancer_id)) return self._to_balancer(balancer[0])
[docs] def create_balancer(self, name, members, protocol='http', port=80, algorithm=DEFAULT_ALGORITHM, location=None, private_port=None, network_id=None, vpc_id=None): """ @inherits: :class:`Driver.create_balancer` :param location: Location :type location: :class:`NodeLocation` :param private_port: Private port :type private_port: ``int`` :param network_id: The guest network this rule will be created for. :type network_id: ``str`` """ args = {} ip_args = {} if location is None: locations = self._sync_request(command='listZones', method='GET') location = locations['zone'][0]['id'] else: location = location.id if private_port is None: private_port = port if network_id is not None: args['networkid'] = network_id ip_args['networkid'] = network_id if vpc_id is not None: ip_args['vpcid'] = vpc_id ip_args.update({'zoneid': location, 'networkid': network_id, 'vpc_id': vpc_id}) result = self._async_request(command='associateIpAddress', params=ip_args, method='GET') public_ip = result['ipaddress'] args.update({'algorithm': self._ALGORITHM_TO_VALUE_MAP[algorithm], 'name': name, 'privateport': private_port, 'publicport': port, 'publicipid': public_ip['id']}) result = self._sync_request( command='createLoadBalancerRule', params=args, method='GET') listbalancers = self._sync_request( command='listLoadBalancerRules', params=args, method='GET') listbalancers = [rule for rule in listbalancers['loadbalancerrule'] if rule['id'] == result['id']] if len(listbalancers) != 1: return None balancer = self._to_balancer(listbalancers[0]) for member in members: balancer.attach_member(member) return balancer
[docs] def destroy_balancer(self, balancer): self._async_request(command='deleteLoadBalancerRule', params={'id': balancer.id}, method='GET') self._async_request(command='disassociateIpAddress', params={'id': balancer.ex_public_ip_id}, method='GET')
[docs] def balancer_attach_member(self, balancer, member): member.port = balancer.ex_private_port self._async_request(command='assignToLoadBalancerRule', params={'id': balancer.id, 'virtualmachineids': member.id}, method='GET') return True
[docs] def balancer_detach_member(self, balancer, member): self._async_request(command='removeFromLoadBalancerRule', params={'id': balancer.id, 'virtualmachineids': member.id}, method='GET') return True
[docs] def balancer_list_members(self, balancer): members = self._sync_request(command='listLoadBalancerRuleInstances', params={'id': balancer.id}, method='GET') members = members['loadbalancerruleinstance'] return [self._to_member(m, balancer.ex_private_port, balancer) for m in members]
def _to_balancer(self, obj): balancer = LoadBalancer( id=obj['id'], name=obj['name'], state=self.LB_STATE_MAP.get(obj['state'], State.UNKNOWN), ip=obj['publicip'], port=obj['publicport'], driver=self.connection.driver ) balancer.ex_private_port = obj['privateport'] balancer.ex_public_ip_id = obj['publicipid'] return balancer def _to_member(self, obj, port, balancer): return Member( id=obj['id'], ip=obj['nic'][0]['ipaddress'], port=port, balancer=balancer )