Edit file File name : libcloud_loadbalancer.py Content :""" 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 import logging import salt.utils.args import salt.utils.compat from salt.utils.versions import LooseVersion as _LooseVersion log = logging.getLogger(__name__) 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: return ( False, "A apache-libcloud library with version at least {} was not found".format( REQUIRED_LIBCLOUD_VERSION ), ) return True 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, str): 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 not match: 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, } Save