You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@libcloud.apache.org by to...@apache.org on 2015/08/30 14:32:57 UTC
[09/21] libcloud git commit: [LIBCLOUD-737] Added create_listener to
create the pool,
add the nodes to the pool and create a virtual listener on the big-ip. Added
docstrings to some of the methods. todo - complete unit tests for extended
methods
[LIBCLOUD-737] Added create_listener to create the pool, add the nodes to the pool and create a virtual listener on the big-ip. Added docstrings to some of the methods. todo - complete unit tests for extended methods
Project: http://git-wip-us.apache.org/repos/asf/libcloud/repo
Commit: http://git-wip-us.apache.org/repos/asf/libcloud/commit/2709109c
Tree: http://git-wip-us.apache.org/repos/asf/libcloud/tree/2709109c
Diff: http://git-wip-us.apache.org/repos/asf/libcloud/diff/2709109c
Branch: refs/heads/trunk
Commit: 2709109c7e015220f4871e93eb345f78241c31b3
Parents: b4ed5ea
Author: Anthony Shaw <an...@gmail.com>
Authored: Wed Aug 26 20:51:19 2015 +1000
Committer: Anthony Shaw <an...@gmail.com>
Committed: Wed Aug 26 20:51:19 2015 +1000
----------------------------------------------------------------------
libcloud/loadbalancer/drivers/dimensiondata.py | 272 +++++++++++++++++++-
1 file changed, 263 insertions(+), 9 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/libcloud/blob/2709109c/libcloud/loadbalancer/drivers/dimensiondata.py
----------------------------------------------------------------------
diff --git a/libcloud/loadbalancer/drivers/dimensiondata.py b/libcloud/loadbalancer/drivers/dimensiondata.py
index e44b77e..dc6d728 100644
--- a/libcloud/loadbalancer/drivers/dimensiondata.py
+++ b/libcloud/loadbalancer/drivers/dimensiondata.py
@@ -84,7 +84,56 @@ class DimensionDataLBDriver(Driver):
return kwargs
def create_balancer(self, name, port, protocol, algorithm, members):
+ """
+ Create a new load balancer instance
+
+ :param name: Name of the new load balancer (required)
+ :type name: ``str``
+
+ :param port: Port the load balancer should listen on, defaults to 80
+ :type port: ``str``
+
+ :param protocol: Loadbalancer protocol, defaults to http.
+ :type protocol: ``str``
+
+ :param members: list of Members to attach to balancer
+ :type members: ``list`` of :class:`Member`
+
+ :param algorithm: Load balancing algorithm, defaults to ROUND_ROBIN.
+ :type algorithm: :class:`.Algorithm`
+
+ :rtype: :class:`LoadBalancer`
+ """
+ # TODO: Figure out which location is used...
+ network_domain_id=None
+
+ # Create a pool first
+ pool_id=self.ex_create_pool(
+ network_domain_id=network_domain_id,
+ name=name,
+ ex_description=None,
+ balancer_method=_ALGORITHM_TO_VALUE_MAP.get(algorithm)
+ )
+ # Attach the members to the pool as nodes
+ for member in members:
+ node_id=self.ex_create_node(
+ network_domain_id=network_domain_id,
+ name=member.name,
+ ip=member.ip,
+ ex_description=None
+ )
+ self.ex_create_pool_member(
+ pool_id=pool_id,
+ node_id=node_id,
+ port=port)
+
+ # Create the virtual listener (balancer)
+ self.ex_create_virtual_listener(
+ network_domain_id=network_domain_id,
+ name=name,
+ ex_description=None,
+ port=port)
return True
def list_balancers(self):
@@ -124,7 +173,7 @@ class DimensionDataLBDriver(Driver):
:rtype: ``list`` of ``str``
"""
- return ['dns', 'ftp', 'http', 'https', 'tcp', 'udp']
+ return ['http', 'https', 'tcp', 'udp']
def balancer_list_members(self, balancer):
"""
@@ -152,37 +201,240 @@ class DimensionDataLBDriver(Driver):
return members
def balancer_attach_member(self, balancer, member):
- return True
+ """
+ Attach a member to balancer
- def balancer_attach_compute_node(self, balancer, node):
+ :param balancer: LoadBalancer which should be used
+ :type balancer: :class:`LoadBalancer`
+
+ :param member: Member to join to the balancer
+ :type member: :class:`Member`
+
+ :return: Member after joining the balancer.
+ :rtype: :class:`Member`
+ """
+
+ nodeId= self.ex_create_node(
+ network_domain_id=balancer.extra['network_domain_id'],
+ name=member.name,
+ ip=member.ip,
+ ex_description=member.description
+ )
+ if nodeId == false:
+ return False
+
+ poolMemberId = self.ex_create_pool_member(balancer.extra['pool_id'],
+ nodeId,
+ member.port)
+
return True
def balancer_detach_member(self, balancer, member):
+ """
+ Detach member from balancer
+
+ :param balancer: LoadBalancer which should be used
+ :type balancer: :class:`LoadBalancer`
+
+ :param member: Member which should be used
+ :type member: :class:`Member`
+
+ :return: ``True`` if member detach was successful, otherwise ``False``.
+ :rtype: ``bool``
+ """
+
+ create_pool_m = ET.Element('removePoolMember', {'xmlns': SERVER_NS,
+ 'id': member.id})
+
+ self.connection.request_with_orgId_api_2(
+ 'networkDomainVip/removePoolMember',
+ method='POST',
+ data=ET.tostring(create_pool_m)).object
+
return True
def destroy_balancer(self, balancer):
+ """
+ Destroy a load balancer (virtual listener)
+
+ :param balancer: LoadBalancer which should be used
+ :type balancer: :class:`LoadBalancer`
+
+ :return: ``True`` if the destroy was successful, otherwise ``False``.
+ :rtype: ``bool``
+ """
+
+ delete_listener = ET.Element('deleteVirtualListener', {'xmlns': SERVER_NS,
+ 'id': balancer.id})
+
+ self.connection.request_with_orgId_api_2(
+ 'networkDomainVip/deleteVirtualListener',
+ method='POST',
+ data=ET.tostring(delete_listener)).object
return True
+ def ex_create_pool_member(self, pool_id, node_id, port):
+ """
+ Create a new member in an existing pool from an existing node
+
+ :param pool_id: ID of the pool (required)
+ :type name: ``str``
+
+ :param node_id: ID of the node (required)
+ :type name: ``str``
+
+ :param port: Port the the service will listen on
+ :type port: ``str``
+
+ :return: ID of the node member, ``False`` if failed to add.
+ :rtype: ``str``
+ """
+ create_pool_m = ET.Element('addPoolMember', {'xmlns': SERVER_NS})
+ ET.SubElement(create_pool_m, "poolId").text = pool_id
+ ET.SubElement(create_pool_m, "nodeId").text = node_id
+ ET.SubElement(create_pool_m, "port").text = port
+
+ response = self.connection.request_with_orgId_api_2(
+ 'networkDomainVip/addPoolMember',
+ method='POST',
+ data=ET.tostring(create_pool_m)).object
+
+ for info in findall(response, 'info', TYPES_URN):
+ if info.name == 'poolMemberId':
+ return info.value
+
+ return False
+
def ex_create_node(self,
network_domain_id,
name,
ip,
ex_description,
- connectionLimit=25000,
- connectionRateLimit=2000):
+ connection_limit=25000,
+ connection_rate_limit=2000):
+ """
+ Create a new node
+
+ :param network_domain_id: Network Domain ID (required)
+ :type name: ``str``
+
+ :param name: name of the node (required)
+ :type name: ``str``
+
+ :param ip: IPv4 address of the node (required)
+ :type ip: ``str``
+
+ :param ex_description: Description of the node
+ :type ex_description: ``str``
+
+ :param connection_limit: Maximum number of concurrent connections per sec
+ :type connection_limit: ``int``
+
+ :param connection_rate_limit: Maximum number of concurrent sessions
+ :type connection_rate_limit: ``int``
+
+ :return: ID of the node, ``False`` if failed to add.
+ :rtype: ``str``
+ """
create_node_elm = ET.Element('createNode', {'xmlns': SERVER_NS})
ET.SubElement(create_node_elm, "networkDomainId").text = network_domain_id
ET.SubElement(create_node_elm, "description").text = ex_description
ET.SubElement(create_node_elm, "name").text = name
ET.SubElement(create_node_elm, "ipv4Address").text = ip
- ET.SubElement(create_node_elm, "connectionLimit").text = connectionLimit
- ET.SubElement(create_node_elm, "connectionRateLimit").text = connectionRateLimit
+ ET.SubElement(create_node_elm, "connectionLimit").text = connection_limit
+ ET.SubElement(create_node_elm, "connectionRateLimit").text = connection_rate_limit
- self.connection.request_with_orgId_api_2(
+ response = self.connection.request_with_orgId_api_2(
'networkDomainVip/createNode',
method='POST',
data=ET.tostring(create_node_elm)).object
- return True
+
+ for info in findall(response, 'info', TYPES_URN):
+ if info.name == 'nodeId':
+ return info.value
+
+ return None
+
+ def ex_create_pool(self,
+ network_domain_id,
+ name,
+ balancer_method,
+ ex_description,
+ service_down_action='NONE',
+ slow_ramp_time=30):
+ """
+ Create a new pool
+
+ :param network_domain_id: Network Domain ID (required)
+ :type name: ``str``
+
+ :param name: name of the node (required)
+ :type name: ``str``
+
+ :param balancer_method: The load balancer algorithm (required)
+ :type balancer_method: ``str``
+
+ :param ex_description: Description of the node
+ :type ex_description: ``str``
+
+ :param service_down_action: What to do when node is unavailable NONE, DROP or RESELECT
+ :type service_down_action: ``str``
+
+ :param slow_ramp_time: Number of seconds to stagger ramp up of nodes
+ :type slow_ramp_time: ``int``
+
+ :return: ID of the pool, ``False`` if failed to add.
+ :rtype: ``str``
+ """
+ create_node_elm = ET.Element('createPool', {'xmlns': SERVER_NS})
+ ET.SubElement(create_node_elm, "networkDomainId").text = network_domain_id
+ ET.SubElement(create_node_elm, "description").text = ex_description
+ ET.SubElement(create_node_elm, "name").text = name
+ ET.SubElement(create_node_elm, "loadBalancerMethod").text = balancer_method
+ ET.SubElement(create_node_elm, "serviceDownAction").text = service_down_action
+ ET.SubElement(create_node_elm, "slowRampTime").text = slow_ramp_time
+
+ response = self.connection.request_with_orgId_api_2(
+ 'networkDomainVip/createPool',
+ method='POST',
+ data=ET.tostring(create_node_elm)).object
+
+ for info in findall(response, 'info', TYPES_URN):
+ if info.name == 'poolId':
+ return info.value
+
+ return False
+
+ def ex_create_virtual_listener(self,
+ network_domain_id,
+ name,
+ ex_description,
+ port,
+ listener_type='STANDARD',
+ protocol='ANY',
+ connection_limit=25000,
+ connection_rate_limit=2000,
+ source_port_preservation='PRESERVE'):
+ create_node_elm = ET.Element('createVirtualListener', {'xmlns': SERVER_NS})
+ ET.SubElement(create_node_elm, "networkDomainId").text = network_domain_id
+ ET.SubElement(create_node_elm, "description").text = ex_description
+ ET.SubElement(create_node_elm, "name").text = name
+ ET.SubElement(create_node_elm, "port").text = port
+ ET.SubElement(create_node_elm, "type").text = listener_type
+ ET.SubElement(create_node_elm, "connectionLimit").text = connection_limit
+ ET.SubElement(create_node_elm, "connectionRateLimit").text = connection_rate_limit
+ ET.SubElement(create_node_elm, "sourcePortPreservation").text = source_port_preservation
+
+ response = self.connection.request_with_orgId_api_2(
+ 'networkDomainVip/createVirtualListener',
+ method='POST',
+ data=ET.tostring(create_node_elm)).object
+
+ for info in findall(response, 'info', TYPES_URN):
+ if info.name == 'poolId':
+ return info.value
+
+ return False
def ex_get_pools(self):
pools = self.connection \
@@ -223,6 +475,8 @@ class DimensionDataLBDriver(Driver):
extra['pool_id'] = element.find(fixxpath(
'pool',
TYPES_URN)).get('id')
+ extra['network_domain_id'] = findtext(element, 'networkDomainId',
+ TYPES_URN)
balancer = LoadBalancer(
id=element.get('id'),