File: //proc/self/root/usr/lib/python2.7/site-packages/salt/modules/libcloud_loadbalancer.py
# -*- coding: utf-8 -*-
'''
Apache Libcloud Load Balancer Management
========================================
Connection module for Apache Libcloud Storage load balancer management for a full list
of supported clouds, see http://libcloud.readthedocs.io/en/latest/loadbalancer/supported_providers.html
Clouds include Amazon ELB, ALB, Google, Aliyun, CloudStack, Softlayer
.. versionadded:: 2018.3.0
:configuration:
This module uses a configuration profile for one or multiple Storage providers
.. code-block:: yaml
libcloud_loadbalancer:
profile_test1:
driver: gce
key: GOOG0123456789ABCXYZ
secret: mysecret
profile_test2:
driver: alb
key: 12345
secret: mysecret
:depends: apache-libcloud
'''
# keep lint from choking on _get_conn and _cache_id
#pylint: disable=E0602
from __future__ import absolute_import, unicode_literals, print_function
# Import Python libs
import logging
# Import salt libs
import salt.utils.args
import salt.utils.compat
from salt.ext import six
from salt.utils.versions import LooseVersion as _LooseVersion
log = logging.getLogger(__name__)
# Import third party libs
REQUIRED_LIBCLOUD_VERSION = '1.5.0'
try:
#pylint: disable=unused-import
import libcloud
from libcloud.loadbalancer.providers import get_driver
from libcloud.loadbalancer.base import Member, Algorithm
#pylint: enable=unused-import
if hasattr(libcloud, '__version__') and _LooseVersion(libcloud.__version__) < _LooseVersion(REQUIRED_LIBCLOUD_VERSION):
raise ImportError()
logging.getLogger('libcloud').setLevel(logging.CRITICAL)
HAS_LIBCLOUD = True
except ImportError:
HAS_LIBCLOUD = False
def __virtual__():
'''
Only load if libcloud libraries exist.
'''
if not HAS_LIBCLOUD:
msg = ('A apache-libcloud library with version at least {0} was not '
'found').format(REQUIRED_LIBCLOUD_VERSION)
return (False, msg)
return True
def __init__(opts):
salt.utils.compat.pack_dunder(__name__)
def _algorithm_maps():
return {
'RANDOM': Algorithm.RANDOM,
'ROUND_ROBIN': Algorithm.ROUND_ROBIN,
'LEAST_CONNECTIONS': Algorithm.LEAST_CONNECTIONS,
'WEIGHTED_ROUND_ROBIN': Algorithm.WEIGHTED_ROUND_ROBIN,
'WEIGHTED_LEAST_CONNECTIONS': Algorithm.WEIGHTED_LEAST_CONNECTIONS,
'SHORTEST_RESPONSE': Algorithm.SHORTEST_RESPONSE,
'PERSISTENT_IP': Algorithm.PERSISTENT_IP
}
def _get_driver(profile):
config = __salt__['config.option']('libcloud_loadbalancer')[profile]
cls = get_driver(config['driver'])
args = config.copy()
del args['driver']
args['key'] = config.get('key')
args['secret'] = config.get('secret', None)
if args['secret'] is None:
del args['secret']
args['secure'] = config.get('secure', True)
args['host'] = config.get('host', None)
args['port'] = config.get('port', None)
return cls(**args)
def list_balancers(profile, **libcloud_kwargs):
'''
Return a list of load balancers.
:param profile: The profile key
:type profile: ``str``
:param libcloud_kwargs: Extra arguments for the driver's list_balancers method
:type libcloud_kwargs: ``dict``
CLI Example:
.. code-block:: bash
salt myminion libcloud_storage.list_balancers profile1
'''
conn = _get_driver(profile=profile)
libcloud_kwargs = salt.utils.args.clean_kwargs(**libcloud_kwargs)
balancers = conn.list_balancers(**libcloud_kwargs)
ret = []
for balancer in balancers:
ret.append(_simple_balancer(balancer))
return ret
def list_protocols(profile, **libcloud_kwargs):
'''
Return a list of supported protocols.
:param profile: The profile key
:type profile: ``str``
:param libcloud_kwargs: Extra arguments for the driver's list_protocols method
:type libcloud_kwargs: ``dict``
:return: a list of supported protocols
:rtype: ``list`` of ``str``
CLI Example:
.. code-block:: bash
salt myminion libcloud_storage.list_protocols profile1
'''
conn = _get_driver(profile=profile)
libcloud_kwargs = salt.utils.args.clean_kwargs(**libcloud_kwargs)
return conn.list_protocols(**libcloud_kwargs)
def create_balancer(name, port, protocol, profile, algorithm=None, members=None, **libcloud_kwargs):
'''
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 algorithm: Load balancing algorithm, defaults to ROUND_ROBIN. See Algorithm type
in Libcloud documentation for a full listing.
:type algorithm: ``str``
:param profile: The profile key
:type profile: ``str``
:param libcloud_kwargs: Extra arguments for the driver's create_balancer method
:type libcloud_kwargs: ``dict``
:return: The details of the new balancer
CLI Example:
.. code-block:: bash
salt myminion libcloud_storage.create_balancer my_balancer 80 http profile1
'''
if algorithm is None:
algorithm = Algorithm.ROUND_ROBIN
else:
if isinstance(algorithm, six.string_types):
algorithm = _algorithm_maps()[algorithm]
starting_members = []
if members is not None:
if isinstance(members, list):
for m in members:
starting_members.append(Member(id=None, ip=m['ip'], port=m['port']))
else:
raise ValueError("members must be of type list")
libcloud_kwargs = salt.utils.args.clean_kwargs(**libcloud_kwargs)
conn = _get_driver(profile=profile)
balancer = conn.create_balancer(name, port, protocol, algorithm, starting_members, **libcloud_kwargs)
return _simple_balancer(balancer)
def destroy_balancer(balancer_id, profile, **libcloud_kwargs):
'''
Destroy a load balancer
:param balancer_id: LoadBalancer ID which should be used
:type balancer_id: ``str``
:param profile: The profile key
:type profile: ``str``
:param libcloud_kwargs: Extra arguments for the driver's destroy_balancer method
:type libcloud_kwargs: ``dict``
:return: ``True`` if the destroy was successful, otherwise ``False``.
:rtype: ``bool``
CLI Example:
.. code-block:: bash
salt myminion libcloud_storage.destroy_balancer balancer_1 profile1
'''
conn = _get_driver(profile=profile)
libcloud_kwargs = salt.utils.args.clean_kwargs(**libcloud_kwargs)
balancer = conn.get_balancer(balancer_id)
return conn.destroy_balancer(balancer, **libcloud_kwargs)
def get_balancer_by_name(name, profile, **libcloud_kwargs):
'''
Get the details for a load balancer by name
:param name: Name of a load balancer you want to fetch
:type name: ``str``
:param profile: The profile key
:type profile: ``str``
:param libcloud_kwargs: Extra arguments for the driver's list_balancers method
:type libcloud_kwargs: ``dict``
:return: the load balancer details
CLI Example:
.. code-block:: bash
salt myminion libcloud_storage.get_balancer_by_name my_balancer profile1
'''
conn = _get_driver(profile=profile)
libcloud_kwargs = salt.utils.args.clean_kwargs(**libcloud_kwargs)
balancers = conn.list_balancers(**libcloud_kwargs)
match = [b for b in balancers if b.name == name]
if len(match) == 1:
return _simple_balancer(match[0])
elif len(match) > 1:
raise ValueError("Ambiguous argument, found mulitple records")
else:
raise ValueError("Bad argument, found no records")
def get_balancer(balancer_id, profile, **libcloud_kwargs):
'''
Get the details for a load balancer by ID
:param balancer_id: id of a load balancer you want to fetch
:type balancer_id: ``str``
:param profile: The profile key
:type profile: ``str``
:param libcloud_kwargs: Extra arguments for the driver's get_balancer method
:type libcloud_kwargs: ``dict``
:return: the load balancer details
CLI Example:
.. code-block:: bash
salt myminion libcloud_storage.get_balancer balancer123 profile1
'''
conn = _get_driver(profile=profile)
libcloud_kwargs = salt.utils.args.clean_kwargs(**libcloud_kwargs)
balancer = conn.get_balancer(balancer_id, **libcloud_kwargs)
return _simple_balancer(balancer)
def list_supported_algorithms(profile, **libcloud_kwargs):
'''
Get the supported algorithms for a profile
:param profile: The profile key
:type profile: ``str``
:param libcloud_kwargs: Extra arguments for the driver's list_supported_algorithms method
:type libcloud_kwargs: ``dict``
:return: The supported algorithms
CLI Example:
.. code-block:: bash
salt myminion libcloud_storage.list_supported_algorithms profile1
'''
conn = _get_driver(profile=profile)
libcloud_kwargs = salt.utils.args.clean_kwargs(**libcloud_kwargs)
return conn.list_supported_algorithms(**libcloud_kwargs)
def balancer_attach_member(balancer_id, ip, port, profile, extra=None, **libcloud_kwargs):
'''
Add a new member to the load balancer
:param balancer_id: id of a load balancer you want to fetch
:type balancer_id: ``str``
:param ip: IP address for the new member
:type ip: ``str``
:param port: Port for the new member
:type port: ``int``
:param profile: The profile key
:type profile: ``str``
:param libcloud_kwargs: Extra arguments for the driver's balancer_attach_member method
:type libcloud_kwargs: ``dict``
CLI Example:
.. code-block:: bash
salt myminion libcloud_storage.balancer_attach_member balancer123 1.2.3.4 80 profile1
'''
conn = _get_driver(profile=profile)
libcloud_kwargs = salt.utils.args.clean_kwargs(**libcloud_kwargs)
member = Member(id=None, ip=ip, port=port, balancer=None, extra=extra)
balancer = conn.get_balancer(balancer_id)
member_saved = conn.balancer_attach_member(balancer, member, **libcloud_kwargs)
return _simple_member(member_saved)
def balancer_detach_member(balancer_id, member_id, profile, **libcloud_kwargs):
'''
Add a new member to the load balancer
:param balancer_id: id of a load balancer you want to fetch
:type balancer_id: ``str``
:param ip: IP address for the new member
:type ip: ``str``
:param port: Port for the new member
:type port: ``int``
:param profile: The profile key
:type profile: ``str``
:param libcloud_kwargs: Extra arguments for the driver's balancer_detach_member method
:type libcloud_kwargs: ``dict``
CLI Example:
.. code-block:: bash
salt myminion libcloud_storage.balancer_detach_member balancer123 member123 profile1
'''
conn = _get_driver(profile=profile)
balancer = conn.get_balancer(balancer_id)
members = conn.balancer_list_members(balancer=balancer)
match = [member for member in members if member.id == member_id]
if len(match) > 1:
raise ValueError("Ambiguous argument, found mulitple records")
elif len(match) == 0:
raise ValueError("Bad argument, found no records")
else:
member = match[0]
libcloud_kwargs = salt.utils.args.clean_kwargs(**libcloud_kwargs)
return conn.balancer_detach_member(balancer=balancer, member=member, **libcloud_kwargs)
def list_balancer_members(balancer_id, profile, **libcloud_kwargs):
'''
List the members of a load balancer
:param balancer_id: id of a load balancer you want to fetch
:type balancer_id: ``str``
:param profile: The profile key
:type profile: ``str``
:param libcloud_kwargs: Extra arguments for the driver's list_balancer_members method
:type libcloud_kwargs: ``dict``
CLI Example:
.. code-block:: bash
salt myminion libcloud_storage.list_balancer_members balancer123 profile1
'''
conn = _get_driver(profile=profile)
balancer = conn.get_balancer(balancer_id)
libcloud_kwargs = salt.utils.args.clean_kwargs(**libcloud_kwargs)
members = conn.balancer_list_members(balancer=balancer, **libcloud_kwargs)
return [_simple_member(member) for member in members]
def extra(method, profile, **libcloud_kwargs):
'''
Call an extended method on the driver
:param method: Driver's method name
:type method: ``str``
:param profile: The profile key
:type profile: ``str``
:param libcloud_kwargs: Extra arguments for the driver's method
:type libcloud_kwargs: ``dict``
CLI Example:
.. code-block:: bash
salt myminion libcloud_loadbalancer.extra ex_get_permissions google container_name=my_container object_name=me.jpg --out=yaml
'''
libcloud_kwargs = salt.utils.args.clean_kwargs(**libcloud_kwargs)
conn = _get_driver(profile=profile)
connection_method = getattr(conn, method)
return connection_method(**libcloud_kwargs)
def _simple_balancer(balancer):
return {
'id': balancer.id,
'name': balancer.name,
'state': balancer.state,
'ip': balancer.ip,
'port': balancer.port,
'extra': balancer.extra
}
def _simple_member(member):
return {
'id': member.id,
'ip': member.ip,
'port': member.port,
'balancer': _simple_balancer(member.balancer),
'extra': member.extra
}