# Copyright (c) 2014 Baidu.com, Inc. All Rights Reserved
#
# Licensed 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.

"""
This module provides a client class for BLB.
"""

import copy
import json
import logging
import uuid
import sys

from baidubce import bce_base_client
from baidubce.auth import bce_v1_signer
from baidubce.http import bce_http_client
from baidubce.http import handler
from baidubce.http import http_methods
from baidubce import utils
from baidubce.utils import required
from baidubce import compat

if sys.version < '3':
    reload(sys)
    sys.setdefaultencoding('utf-8')

_logger = logging.getLogger(__name__)


class BlbClient(bce_base_client.BceBaseClient):
    """
    BLB base sdk client
    """
    version = b'/v1'

    def __init__(self, config=None):
        bce_base_client.BceBaseClient.__init__(self, config)

    def _merge_config(self, config=None):
        """
        :param config:
        :type config: baidubce.BceClientConfiguration
        :return:
        """
        if config is None:
            return self.config
        else:
            new_config = copy.copy(self.config)
            new_config.merge_non_none_values(config)
            return new_config

    def _send_request(self, http_method, path,
                      body=None, headers=None, params=None,
                      config=None, body_parser=None):
        config = self._merge_config(config)
        if body_parser is None:
            body_parser = handler.parse_json
        if headers is None:
            headers = {b'Accept': b'*/*',
                       b'Content-Type': b'application/json;charset=utf-8'}
        return bce_http_client.send_request(
            config, bce_v1_signer.sign, [handler.parse_error, body_parser],
            http_method, path, body, headers, params)

    @required(vpc_id=(bytes, str),
              subnet_id=(bytes, str))
    def create_loadbalancer(self, vpc_id, subnet_id, name=None,
                            desc=None, address=None, blb_type=None, eip=None,
                            tags=None, billing=None, performance_level=None,
                            auto_renew_length=None, auto_renew_time_unit=None,
                            resource_group_id=None, allow_delete=None,
                            allocate_ipv6=None, client_token=None, config=None):
        """
        Create a LoadBalancer with the specified options.

        :param name:
                the name of LoadBalancer to create
        :type name: string

        :param desc:
                The description of LoadBalancer
        :type desc: string

        :param vpc_id:
                id of vpc which the LoadBalancer belong to
        :type vpc_id: string

        :param subnet_id:
                id of subnet which the LoadBalancer belong to
        :type subnet_id: string

        :param address:
                The private IP address of the LoadBalancer
        :type address: string

        :param blb_type:
                The type of LoadBalancer
        :type blb_type: string

        :param eip:
                The EIP to bind to the LoadBalancer
        :type eip: string

        :param tags:
                The tags for the LoadBalancer
        :type tags: list

        :param billing:
                The billing information
        :type billing: dict

        :param performance_level:
                The performance level of the LoadBalancer
        :type performance_level: string

        :param auto_renew_length:
                The length of auto renew
        :type auto_renew_length: int

        :param auto_renew_time_unit:
                The time unit of auto renew
        :type auto_renew_time_unit: string

        :param resource_group_id:
                The resource group ID
        :type resource_group_id: string

        :param allow_delete:
                Whether to allow deletion
        :type allow_delete: bool

        :param allocate_ipv6:
                Whether to allocate IPv6 address
        :type allocate_ipv6: bool

        :param client_token:
            If the clientToken is not specified by the user, a random String
            generated by default algorithm will be used.
        :type client_token: string

        :param config:
        :type config: baidubce.BceClientConfiguration

        :return:
        :rtype baidubce.bce_response.BceResponse
        """
        path = utils.append_uri(self.version, 'blb')
        params = {}

        if client_token is None:
            params[b'clientToken'] = generate_client_token()
        else:
            params[b'clientToken'] = client_token

        body = {}
        if name is not None:
            body['name'] = compat.convert_to_string(name)
        if desc is not None:
            body['desc'] = compat.convert_to_string(desc)
        body['vpcId'] = compat.convert_to_string(vpc_id)
        body['subnetId'] = compat.convert_to_string(subnet_id)
        if address is not None:
            body['address'] = compat.convert_to_string(address)
        if blb_type is not None:
            body['type'] = compat.convert_to_string(blb_type)
        if eip is not None:
            body['eip'] = compat.convert_to_string(eip)
        if tags is not None:
            body['tags'] = tags
        if billing is not None:
            body['billing'] = billing
        if performance_level is not None:
            body['performanceLevel'] = compat.convert_to_string(performance_level)
        if auto_renew_length is not None:
            body['autoRenewLength'] = auto_renew_length
        if auto_renew_time_unit is not None:
            body['autoRenewTimeUnit'] = compat.convert_to_string(auto_renew_time_unit)
        if resource_group_id is not None:
            body['resourceGroupId'] = compat.convert_to_string(resource_group_id)
        if allow_delete is not None:
            body['allowDelete'] = allow_delete
        if allocate_ipv6 is not None:
            body['allocateIpv6'] = allocate_ipv6

        return self._send_request(http_methods.POST, path,
                                  body=json.dumps(body), params=params,
                                  config=config)

    def describe_loadbalancers(self, address=None, name=None, blb_id=None,
                               bcc_id=None, exactly_match=None, marker=None, 
                               max_keys=None, blb_type=None, config=None):
        """
        Return a list of LoadBalancers

        :param address:
            Intranet service address in dotted decimal notation
        :type address: string

        :param name:
            name of LoadBalancer to describe
        :type name: string

        :param blb_id:
            id of LoadBalancer to describe
        :type blb_id: string

        :param bcc_id:
            bcc which bind the LoadBalancers
        :type bcc_id: string

        :param exactly_match:
            Whether to match exactly
        :type exactly_match: bool

        :param marker:
            The optional parameter marker specified in the original
            request to specify where in the results to begin listing.
            Together with the marker, specifies the list result
            which listing should begin.
            If the marker is not specified, the list result will
            listing from the first one.
        :type marker: string

        :param max_keys
        The optional parameter to specifies the max number of list
        result to return.
            The default value is 1000.
        :type max_keys: int

        :param blb_type:
            The type of LoadBalancer
        :type blb_type: string

        :param config:
        :type config: baidubce.BceClientConfiguration

        :return:
        :rtype baidubce.bce_response.BceResponse
        """
        path = utils.append_uri(self.version, 'blb')
        params = {}

        if address is not None:
            params[b'address'] = address
        if name is not None:
            params[b'name'] = name
        if blb_id is not None:
            params[b'blbId'] = blb_id
        if bcc_id is not None:
            params[b'bccId'] = bcc_id
        if exactly_match is not None:
            params[b'exactlyMatch'] = exactly_match
        if marker is not None:
            params[b'marker'] = marker
        if max_keys is not None:
            params[b'maxKeys'] = max_keys
        if blb_type is not None:
            params[b'type'] = blb_type

        return self._send_request(http_methods.GET, path,
                                  params=params, config=config)

    @required(blb_id=(bytes, str))
    def describe_loadbalancer_detail(self, blb_id, config=None):
        """
        Return detail imformation of specific LoadBalancer

        :param blb_id:
            id of LoadBalancer to describe
        :type blb_id: string

        :param config:
        :type config: baidubce.BceClientConfiguration

        :return:
        :rtype baidubce.bce_response.BceResponse
        """
        path = utils.append_uri(self.version, 'blb', blb_id)

        return self._send_request(http_methods.GET, path,
                                  config=config)

    @required(blbId=(bytes, str))
    def update_loadbalancer(self, blb_id, name=None, desc=None,
                            allow_delete=None, allocate_ipv6=None,
                            client_token=None, config=None):
        """
        Modify the special attribute to new value of the LoadBalancer
        owned by the user.

        :param name:
                name of LoadBalancer to describe
        :type name: string

        :param blb_id:
                id of LoadBalancer to describe
        :type blb_id: string

        :param desc:
                The description of LoadBalancer
        :type desc: string

        :param allow_delete:
                Whether to allow deletion
        :type allow_delete: bool

        :param allocate_ipv6:
                Whether to allocate IPv6 address
        :type allocate_ipv6: bool

        :param client_token:
                If the clientToken is not specified by the user,
                a random String generated by default algorithm
                will be used.
        :type client_token: string

        :param config:
        :type config: baidubce.BceClientConfiguration

        :return:
        :rtype baidubce.bce_response.BceResponse
        """
        path = utils.append_uri(self.version, 'blb', blb_id)
        params = {}

        if client_token is None:
            params[b'clientToken'] = generate_client_token()
        else:
            params[b'clientToken'] = client_token

        body = {}
        if name is not None:
            body['name'] = compat.convert_to_string(name)
        if desc is not None:
            body['desc'] = compat.convert_to_string(desc)
        if allow_delete is not None:
            body['allowDelete'] = allow_delete
        if allocate_ipv6 is not None:
            body['allocateIpv6'] = allocate_ipv6

        return self._send_request(http_methods.PUT, path, json.dumps(body),
                                  params=params, config=config)

    @required(blb_id=(bytes, str))
    def delete_loadbalancer(self, blb_id, client_token=None, config=None):
        """
        delete the LoadBalancer owned by the user.

        :param blb_id:
                id of LoadBalancer to describe
        :type blb_id: string

        :param client_token:
                If the clientToken is not specified by the user,
                a random String generated by default algorithm
                will be used.
        :type client_token: string

        :param config:
        :type config: baidubce.BceClientConfiguration

        :return:
        :rtype baidubce.bce_response.BceResponse
        """
        path = utils.append_uri(self.version, 'blb', blb_id)
        params = {}

        if client_token is None:
            params[b'clientToken'] = generate_client_token()
        else:
            params[b'clientToken'] = client_token
        return self._send_request(http_methods.DELETE, path,
                                  params=params, config=config)

    @required(blb_id=(bytes, str))
    def update_loadbalancer_acl(self, blb_id, client_token=None, support_acl=None, config=None):
        """
        update the specified LoadBalancer to support the acl feature.

        :param blb_id:
                id of LoadBalancer to describe
        :type blb_id: string

        :param client_token:
                If the clientToken is not specified by the user,
                a random String generated by default algorithm
                will be used.
        :type client_token: string

        :param support_acl:
                parameters to support LoadBalancer acl, default is true.
        :type support_acl: Boolean

        :param config:
        :type config: baidubce.BceClientConfiguration

        :return:
        :rtype baidubce.bce_response.BceResponse
        """
        path = utils.append_uri(self.version, 'blb/acl', blb_id)
        params = {}

        if client_token is None:
            params[b'clientToken'] = generate_client_token()
        else:
            params[b'clientToken'] = client_token

        body = {}
        if support_acl is not None:
            body['supportAcl'] = support_acl
        else:
            body['supportAcl'] = True

        return self._send_request(http_methods.PUT, path, json.dumps(body),
                                  params=params, config=config)

    @required(vpc_id=(bytes, str),
              subnet_id=(bytes, str))
    def create_ipv6_loadbalancer(self, vpc_id, subnet_id, name=None,
                                 desc=None, client_token=None, config=None):
        """
        Create a LoadBalancer with the specified options.

        :param name:
                the name of LoadBalancer to create
        :type name: string

        :param desc:
                The description of LoadBalancer
        :type desc: string

        :param vpc_id:
                id of vpc which the LoadBalancer belong to
        :type vpc_id: string

        :param subnet_id:
                id of subnet which the LoadBalancer belong to
        :type subnet_id: string

        :param client_token:
            If the clientToken is not specified by the user, a random String
            generated by default algorithm will be used.
        :type client_token: string

        :param config:
        :type config: baidubce.BceClientConfiguration

        :return:
        :rtype baidubce.bce_response.BceResponse
        """
        path = utils.append_uri(self.version, 'blb')
        params = {}

        if client_token is None:
            params[b'clientToken'] = generate_client_token()
        else:
            params[b'clientToken'] = client_token

        body = {}
        if name is not None:
            body['name'] = compat.convert_to_string(name)
        if desc is not None:
            body['desc'] = compat.convert_to_string(desc)
        body['vpcId'] = compat.convert_to_string(vpc_id)
        body['subnetId'] = compat.convert_to_string(subnet_id)
        body['type'] = compat.convert_to_string('ipv6')

        return self._send_request(http_methods.POST, path,
                                  body=json.dumps(body), params=params,
                                  config=config)

    def describe_ipv6_loadbalancers(self, address=None, name=None, blb_id=None,
                                    bcc_id=None, marker=None, max_keys=None,
                                    config=None):
        """
        Return a list of LoadBalancers

        :param address:
            Intranet service address in dotted decimal notation
        :type address: string

        :param name:
            name of LoadBalancer to describe
        :type name: string

        :param blb_id:
            id of LoadBalancer to describe
        :type blb_id: string

        :param bcc_id:
            bcc which bind the LoadBalancers
        :type bcc_id: string

        :param marker:
            The optional parameter marker specified in the original
            request to specify where in the results to begin listing.
            Together with the marker, specifies the list result
            which listing should begin.
            If the marker is not specified, the list result will
            listing from the first one.
        :type marker: string

        :param max_keys
        The optional parameter to specifies the max number of list
        result to return.
            The default value is 1000.
        :type max_keys: int

        :param config:
        :type config: baidubce.BceClientConfiguration

        :return:
        :rtype baidubce.bce_response.BceResponse
        """
        path = utils.append_uri(self.version, 'blb')
        params = {}

        if address is not None:
            params[b'address'] = address
        if name is not None:
            params[b'name'] = name
        if blb_id is not None:
            params[b'blbId'] = blb_id
        if bcc_id is not None:
            params[b'bccId'] = bcc_id
        if marker is not None:
            params[b'marker'] = marker
        if max_keys is not None:
            params[b'maxKeys'] = max_keys

        params[b'type'] = compat.convert_to_string('ipv6')

        return self._send_request(http_methods.GET, path,
                                  params=params, config=config)

    @required(blb_id=(bytes, str),
              listener_port=int,
              backend_port=int,
              scheduler=(bytes, str))
    def create_tcp_listener(self, blb_id, listener_port,
                            backend_port, scheduler,
                            tcp_session_timeout=None,
                            health_check_type=None,
                            health_check_timeout_in_second=None,
                            health_check_interval=None,
                            unhealthy_threshold=None,
                            healthy_threshold=None,
                            client_token=None, config=None):
        """
        Create a tcp listener rule with the specified options.

        :param blb_id:
            the id of blb which the listener work on
        :type blb_id: string

        :param listener_port:
            port to be linstened owned by listener
        :value 1-65535
        :type listener_port: int

        :param backend_port:
            port to be listened owned by Backend server
        :value 1-65535
        :type backend_port: int

        :param scheduler
            balancing algorithm
        :value 'RoundRobin' or 'LeastConnection' or 'Hash'
        :type scheduler: string

        :param tcp_session_timeout
            TCP session timeout
        :value 10-4000, default: 900, unit: seconds
        :type tcp_session_timeout: int

        :param health_check_type
            Health check protocol type
        :value default: 'TCP'
        :type health_check_type: string

        :param health_check_timeout_in_second
            Health check timeout
        :value 1-60, default: 3, unit: seconds
        :type health_check_timeout_in_second: int

        :param health_check_interval
            Health check interval
        :value 1-10, default: 3, unit: seconds
        :type health_check_interval: int

        :param unhealthy_threshold
            Unhealthy threshold,
            how many consecutive health check failures,
            shielding the backend server
        :value 2-5, default: 3
        :type unhealthy_threshold: int

        :param healthy_threshold
            Health threshold,
            how many consecutive health checks are successful,
            then re-use the back-end server
        :value 2-5, default: 3
        :type healthy_threshold: int

        :param client_token:
            If the clientToken is not specified by the user, a random String
            generated by default algorithm will be used.
        :type client_token: string

         :param config:
        :type config: baidubce.BceClientConfiguration

        :return:
        :rtype baidubce.bce_response.BceResponse
        """
        path = utils.append_uri(self.version, 'blb', blb_id, 'TCPlistener')
        params = {}

        if client_token is None:
            params[b'clientToken'] = generate_client_token()
        else:
            params[b'clientToken'] = client_token

        body = {
            'listenerPort': listener_port,
            'backendPort': backend_port,
            'scheduler': compat.convert_to_string(scheduler)
        }

        if tcp_session_timeout is not None:
            body['tcpSessionTimeout'] = tcp_session_timeout
        if health_check_type is not None:
            body['healthCheckType'] = compat.convert_to_string(health_check_type)
        if health_check_timeout_in_second is not None:
            body['healthCheckTimeoutInSecond'] = \
                health_check_timeout_in_second
        if health_check_interval is not None:
            body['healthCheckInterval'] = health_check_interval
        if unhealthy_threshold is not None:
            body['unhealthyThreshold'] = unhealthy_threshold
        if healthy_threshold is not None:
            body['healthyThreshold'] = healthy_threshold

        return self._send_request(http_methods.POST, path,
                                  body=json.dumps(body), params=params,
                                  config=config)

    @required(blb_id=(bytes, str),
              listener_port=int,
              backend_port=int,
              scheduler=(bytes, str))
    def create_udp_listener(self, blb_id, listener_port, backend_port,
                            scheduler, health_check_string=None,
                            health_check_type=None,
                            health_check_port=None,
                            health_check_timeout_in_second=None,
                            health_check_interval=None,
                            unhealthy_threshold=None,
                            healthy_threshold=None,
                            udp_session_timeout=None,
                            client_token=None, config=None):
        """
        Create a udp listener rule with the specified options.

        :param blb_id:
            the id of blb which the listener work on
        :type blb_id: string

        :param listener_port:
            port to be linstened owned by listener
        :value 1-65535
        :type listener_port: int

        :param backend_port:
            port to be listened owned by Backend server
        :value 1-65535
        :type backend_port: int

        :param scheduler
            balancing algorithm
        :value 'RoundRobin' or 'LeastConnection' or 'Hash'
        :type scheduler: string

        :param health_check_string
            The request string sent by the health,
            the backend server needs to respond after receiving it.
            Required when healthCheckType is 'UDP'.
        :type health_check_string: string

        :param health_check_type
            Health check protocol
        :value 'UDP' or 'ICMP', default: 'UDP'
        :type health_check_type: string

        :param health_check_port
            Health check port, the default is the same as backend_port.
        :type health_check_port: int

        :param health_check_timeout_in_second
            Health check timeout
        :value 1-60, default: 3, unit: seconds
        :type health_check_timeout_in_second: int

        :param health_check_interval
            Health check interval
        :value 1-10, default: 3, unit: seconds
        :type health_check_interval: int

       :param unhealthy_threshold
            Unhealthy threshold,
            how many consecutive health check failures,
            shielding the backend server
        :value 2-5, default: 3
        :type unhealthy_threshold: int

        :param healthy_threshold
            Health threshold,
            how many consecutive health checks are successful,
            then re-use the back-end server
        :value 2-5, default: 3
        :type healthy_threshold: int

        :param udp_session_timeout
            UDP session timeout
        :value 5-4000, default: 90, unit: seconds
        :type udp_session_timeout: int

        :param client_token:
            If the clientToken is not specified by the user, a random String
            generated by default algorithm will be used.
        :type client_token: string

         :param config:
        :type config: baidubce.BceClientConfiguration

        :return:
        :rtype baidubce.bce_response.BceResponse
        """
        path = utils.append_uri(self.version, 'blb', blb_id, 'UDPlistener')
        params = {}

        if client_token is None:
            params[b'clientToken'] = generate_client_token()
        else:
            params[b'clientToken'] = client_token

        body = {
            'listenerPort': listener_port,
            'backendPort': backend_port,
            'scheduler': compat.convert_to_string(scheduler)
        }

        if health_check_string is not None:
            body['healthCheckString'] = compat.convert_to_string(health_check_string)
        if health_check_type is not None:
            body['healthCheckType'] = compat.convert_to_string(health_check_type)
        if health_check_port is not None:
            body['healthCheckPort'] = health_check_port
        if health_check_timeout_in_second is not None:
            body['healthCheckTimeoutInSecond'] = \
                health_check_timeout_in_second
        if health_check_interval is not None:
            body['healthCheckInterval'] = health_check_interval
        if unhealthy_threshold is not None:
            body['unhealthyThreshold'] = unhealthy_threshold
        if healthy_threshold is not None:
            body['healthyThreshold'] = healthy_threshold
        if udp_session_timeout is not None:
            body['udpSessionTimeout'] = udp_session_timeout

        return self._send_request(http_methods.POST, path,
                                  body=json.dumps(body), params=params,
                                  config=config)

    @required(blb_id=(bytes, str), listener_port=int,
              backend_port=int, scheduler=(bytes, str))
    def create_http_listener(self, blb_id, listener_port,
                             backend_port, scheduler,
                             keep_session=None, keep_session_type=None,
                             keep_session_duration=None,
                             keep_session_cookie_name=None,
                             x_forward_for=None,
                             x_forwarded_proto=None,
                             additional_attributes=None,
                             health_check_type=None, health_check_port=None,
                             health_check_uri=None,
                             health_check_timeout_in_second=None,
                             health_check_interval=None,
                             unhealthy_threshold=None,
                             healthy_threshold=None,
                             health_check_normal_status=None,
                             health_check_host=None,
                             server_timeout=None, redirect_port=None,
                             client_token=None, config=None):
        """
        Create a http listener rule with the specified options.
        :param blb_id:
            the id of blb which the listener work on
        :type blb_id: string
        :param listener_port:
            port to be linstened owned by listener
        :value 1-65535
        :type listener_port: int
        :param backend_port:
            port to be listened owned by Backend server
        :value 1-65535
        :type backend_port: int
        :param scheduler:
            balancing algorithm
        :value 'RoundRobin' or 'LeastConnection'
        :type scheduler: string
        :param keep_session:
            Whether to enable the session hold function,
            that is,the request sent by the same client will
            reach the same backend server
        :value true or false  default:false
        :type keep_session: bool
        :param keep_session_type:
            The cookie handling method maintained by the session,
            valid only if the session is held open
            :value 'insert' or 'rewrite'  default:insert
        :type keep_session_type: string
        :param keep_session_duration:
            The time the cookie is kept in session (in seconds),
            valid only if the session is held open
            :value 1-15552000  default:3600
        :type keep_session_duration: int
        :param keep_session_cookie_name:
            The session keeps the name of the cookie that needs to be
            overridden if and only if session persistence is enabled
            and keep_session_type="rewrite"
        :type keep_session_cookie_name: int
        :param x_forward_for:
            Whether to enable the real IP address of the client,
            the backend server can obtain the real address of the client
            through the X-Forwarded-For HTTP header.
        :value true or false, default: False
        :type x_forward_for: bool
        :param health_check_type:
            Health check protocol
        :value 'HTTP' or 'TCP'
        :type health_check_type: string
        :param health_check_port:
            Health check port, the default is the same as backend_port
        :type health_check_port: int
        :param health_check_uri:
            Health check URI, default '/'.
            Effective when the health check protocol is "HTTP"
        :type health_check_uri: string
        :param health_check_timeout_in_second:
            Health check timeout (unit: second)
            :value 1-60, default: 3
        :type health_check_timeout_in_second: int
        :param health_check_interval:
            Health check interval (unit: second)
            :value 1-10, default: 3
        :type health_check_interval: int
        :param unhealthy_threshold:
            The unhealthy threshold, that is,
            how many consecutive health check failures,
            shields the backend server.
        :value 2-5, default: 3
        :type unhealthy_threshold: int
        :param healthy_threshold:
            Health threshold, that is,
            how many consecutive health checks are successful,
            then re-use the back-end server
        value: 2-5, default: 3
        :type health_threshold: int
        :param health_check_normal_status:
            The HTTP status code when the health check is normal supports
            a combination of five types of status codes,
            such as "http_1xx|http_2xx",
            Effective when the health check protocol is "HTTP"
        :value default:http_2xx|http_3xx
        :type health_check_normal_status:string
        :param server_timeout:
            Backend server maximum timeout (unit: second)
        :value 1-3600, default: 30
        :type server_timeout:int
        :param redirect_port:
            Forward the request received by this listener to the
            HTTPS listener, which is specified by the HTTPS listener.
        :type redirect_port:int
        :param client_token:
            If the clientToken is not specified by the user,
            a random String generated by default algorithm will be used.
        :type client_token: string
        :param config:
        :type config: baidubce.BceClientConfiguration
        :return:
        :rtype baidubce.bce_response.BceResponse
        """
        path = utils.append_uri(self.version, 'blb', blb_id, 'HTTPlistener')
        params = {}
        if client_token is None:
            params[b'clientToken'] = generate_client_token()
        else:
            params[b'clientToken'] = client_token
        body = {
            'listenerPort': listener_port,
            'backendPort': backend_port,
            'scheduler': compat.convert_to_string(scheduler)}
        if keep_session is not None:
            body['keepSession'] = keep_session
        if keep_session_type is not None:
            body['keepSessionType'] = keep_session_type
        if keep_session_duration is not None:
            body['keepSessionDuration'] = keep_session_duration
        if keep_session_cookie_name is not None:
            body['keepSessionCookieName'] = keep_session_cookie_name
        if x_forward_for is not None:
            body['xForwardFor'] = x_forward_for
        if x_forwarded_proto is not None:
            body['xForwardedProto'] = x_forwarded_proto
        if additional_attributes is not None:
            body['additionalAttributes'] = additional_attributes
        if health_check_type is not None:
            body['healthCheckType'] = \
                compat.convert_to_string(health_check_type)
        if health_check_port is not None:
            body['healthCheckPort'] = health_check_port
        if health_check_uri is not None:
            body['healthCheckURI'] = \
                compat.convert_to_string(health_check_uri)
        if health_check_timeout_in_second is not None:
            body['healthCheckTimeoutInSecond'] = \
                health_check_timeout_in_second
        if health_check_interval is not None:
            body['healthCheckInterval'] = health_check_interval
        if unhealthy_threshold is not None:
            body['unhealthyThreshold'] = unhealthy_threshold
        if healthy_threshold is not None:
            body['healthyThreshold'] = healthy_threshold
        if health_check_normal_status is not None:
            body['healthCheckNormalStatus'] = \
                compat.convert_to_string(health_check_normal_status)
        if health_check_host is not None:
            body['healthCheckHost'] = compat.convert_to_string(health_check_host)
        if server_timeout is not None:
            body['serverTimeout'] = server_timeout
        if redirect_port is not None:
            body['redirectPort'] = redirect_port
        return self._send_request(http_methods.POST, path,
                                  body=json.dumps(body), params=params,
                                  config=config)

    @required(blb_id=(bytes, str), listener_port=int,
              backend_port=int, scheduler=(bytes, str), cert_ids=list)
    def create_https_listener(self, blb_id, listener_port, backend_port,
                              scheduler, cert_ids, keep_session=None,
                              keep_session_type=None,
                              keep_session_duration=None,
                              keep_session_cookie_name=None,
                              x_forward_for=None,
                              x_forwarded_proto=None,
                              additional_attributes=None,
                              health_check_type=None,
                              health_check_port=None, health_check_uri=None,
                              health_check_timeout_in_second=None,
                              health_check_interval=None,
                              unhealth_threshold=None, health_threshold=None,
                              health_check_normal_status=None,
                              health_check_host=None,
                              server_timeout=None, ie6_compatible=None,
                              encryption_type=None, encryption_protocols=None,
                              applied_ciphers=None,
                              dual_auth=None, client_certIds=None,
                              additional_cert_domains=None,
                              client_token=None, config=None):
        """
        Create a https listener rule with the specified options
        :param blb_id:
            The id of blb which the listener work on
        :type blb_id: string
        :param listener_port:
            port to be linstened owned by listener
        :value 1-65535
        :type listener_port: int
        :param backend_port:
            Port to be listened owned by Backend server
        :value 1-65535
        :type backend_port: int
        :param scheduler:
            balancing algorithm
        :value 'RoundRobin' or 'LeastConnection'
        :type scheduler: string
        :param cert_ids:
            The certificate to be loaded by the listener.
        :type cert_ids: List<String>
        :param keep_session:
            Whether to enable the session hold function,
            that is, the request sent by the same client will reach the
            same backend server
        :value true or false, default: false
        :type keep_session: bool
        :param keep_session_type:
            The cookie handling method maintained by the session,
            valid only if the session is held open
        :value 'insert' or 'rewrite', default:insert
        :type keep_session_type: string
        :param keep_session_duration:
            The time the cookie is kept in session (in seconds),
            valid only if the session is held open
        :value 1-15552000, default:3600
        :type keep_session_duration: int
        :param keep_session_cookie_name:
            The session keeps the name of the cookie that needs
            to be overridden if and only if session persistence
            is enabled and keep_session_type="rewrite"
        :type keep_session_cookie_name: int
        :param x_forward_for:
            Whether to enable the real IP address of the client,
            the backend server can obtain the real address of the client
            through the X-Forwarded-For HTTP header.
        :value true or false, default: flase
        :type x_forward_for: bool
        :param health_check_type:
            Health check protocol
        :value 'HTTP' or 'TCP'
        :type health_check_type: string
        :param health_check_port:
            Health check port, the default is the same as backend_port
        :type health_check_port: int
        :param health_check_uri:
            Health check URI, default '/'.
            Effective when the health check protocol is "HTTP"
        :type health_check_uri: string
        :param health_check_timeout_in_second:
            Health check timeout (unit: second)
            :value 1-60, default:3
        :type health_check_timeout_in_second: int
        :param health_check_interval:
            Health check interval (unit: second)
        :value 1-10, default: 3
        :type health_check_interval: int
        :param unhealth_threshold:
            The unhealthy threshold, that is, how many consecutive health
             check failures, shields the backend server.
        :value 2-5, default: 3
        :type unhealth_threshold: int
        :param health_threshold:
            Health threshold, that is, how many consecutive health checks
             are successful, then re-use the back-end server
        :value:2-5, default: 3
        :type health_threshold: int
        :param health_check_normal_status:
            The HTTP status code when the health check is normal
            supports a combination of five types of status codes,
            such as "http_1xx|http_2xx", Effective when the health check
            protocol is "HTTP"
        :value default: http_2xx|http_3xx
        :type health_check_normal_status: string
        :param server_timeout:
            Backend server maximum timeout (unit: second)
        :value 1-3600, default: 30
        :type server_timeout: int
        :param ie6_compatible:
            compatible with IE6 HTTPS request
            (the protocol format is earlier SSL3.0, the security is poor)
        :value true or false, default: true
        :type ie6_compatible: bool
        :param encryption_type:
            Encryption options, support three types:
            compatibleIE or incompatibleIE or userDefind,
            corresponding to:
            IE-compatible encryption or disabled unsecure encryption
            or custom encryption,
            when encryptionType is valid and legitimate,
            ie6Compatible field transfer value will not take effect
        type: encryption_type:string
        :param encryption_protocols:
            When the encryptionType value is userDefind,
            the list of protocol types is a string list composed of four protocols:
            "sslv3", "tlsv10", "tlsv11", "tlsv12".
        type: encryption_protocols:list
        :param dual_auth:
            Whether to Open Two-way Authentication,
            default:false
        :type dual_auth: boolean
        :param client_certIds:
            When dualAuth is true, the loaded client certificate chain
        :type client_certIds: list
        :param additional_cert_domains:
            Additional domain name,each element is an object that contains two attributes, namely "certId" and "host"
        :type additional_cert_domains: list
        :param client_token:
            If the clientToken is not specified by the user,
            a random String generated by default algorithm will be used.
        :type client_token: string
        :param config:
        :type config: baidubce.BceClientConfiguration
        :return
        :rtype baidubce.bce_response.BceResponse
        """
        path = utils.append_uri(self.version, 'blb', blb_id, 'HTTPSlistener')
        params = {}
        if client_token is None:
            params[b'clientToken'] = generate_client_token()
        else:
            params[b'clientToken'] = client_token
        body = {
            'listenerPort': listener_port, 'backendPort': backend_port,
            'scheduler': compat.convert_to_string(scheduler),
            'certIds': cert_ids}
        if keep_session is not None:
            body['keepSession'] = keep_session
        if keep_session_type is not None:
            body['keepSessionType'] = \
                compat.convert_to_string(keep_session_type)
        if keep_session_duration is not None:
            body['keepSessionDuration'] = keep_session_duration
        if keep_session_cookie_name is not None:
            body['keepSessionCookieName'] = keep_session_cookie_name
        if x_forward_for is not None:
            body['xForwardFor'] = x_forward_for
        if x_forwarded_proto is not None:
            body['xForwardedProto'] = x_forwarded_proto
        if additional_attributes is not None:
            body['additionalAttributes'] = additional_attributes
        if health_check_type is not None:
            body['healthCheckType'] = \
                compat.convert_to_string(health_check_type)
        if health_check_port is not None:
            body['healthCheckPort'] = health_check_port
        if health_check_uri is not None:
            body['healthCheckURI'] = \
                compat.convert_to_string(health_check_uri)
        if health_check_timeout_in_second is not None:
            body['healthCheckTimeoutInSecond'] = \
                health_check_timeout_in_second
        if health_check_interval is not None:
            body['healthCheckInterval'] = health_check_interval
        if unhealth_threshold is not None:
            body['unhealthyThreshold'] = unhealth_threshold
        if health_threshold is not None:
            body['healthyThreshold'] = health_threshold
        if health_check_normal_status is not None:
            body['healthCheckNormalStatus'] = \
                compat.convert_to_string(health_check_normal_status)
        if health_check_host is not None:
            body['healthCheckHost'] = compat.convert_to_string(health_check_host)
        if server_timeout is not None:
            body['serverTimeout'] = server_timeout
        if ie6_compatible is not None:
            body['ie6Compatible'] = ie6_compatible
        if encryption_type is not None:
            body['encryptionType'] = \
                compat.convert_to_string(encryption_type)
        if encryption_protocols is not None:
            body['encryptionProtocols'] = encryption_protocols
        if applied_ciphers is not None:
            body['appliedCiphers'] = compat.convert_to_string(applied_ciphers)
        if dual_auth is not None:
            body['dualAuth'] = dual_auth
        if client_certIds is not None:
            body['clientCertIds'] = client_certIds
        if additional_cert_domains is not None:
            body['additionalCertDomains'] = additional_cert_domains
        return self._send_request(http_methods.POST, path,
                                  body=json.dumps(body),
                                  params=params, config=config)

    @required(blb_id=(bytes, str), listener_port=int,
              backend_port=int, scheduler=(bytes, str), cert_ids=list)
    def create_ssl_listener(self, blb_id, listener_port, backend_port,
                            scheduler, cert_ids,
                            health_check_type=None,
                            server_timeout=None,
                            health_check_timeout_in_second=None,
                            health_check_interval=None,
                            unhealth_threshold=None, health_threshold=None,
                            ie6_compatible=None, encryption_type=None,
                            encryption_protocols=None,
                            applied_ciphers=None,
                            dual_auth=None, client_certIds=None,
                            client_token=None, config=None):
        """
        Create a ssl listener rule with thSe specified options.
        :param blb_id:
            The id of blb which the listener work on
        :type blb_id: string
        :param listener_port:
            port to be linstened owned by listener
        :value 1-65535
        :type listener_port: int
        :param backend_port:
            Port to be listened owned by Backend server
        :value 1-65535
        :type backend_port: int
        :param scheduler:
            balancing algorithm
        :value 'RoundRobin' or 'LeastConnection'
        :type scheduler: string
        :param cert_ids:
            The SSL certificate to be loaded by the listener.
            Currently HTTPS listeners can only bind one SSL certificate.
        :type cert_ids: List<String>
        :param health_check_timeout_in_second:
            Health check timeout (unit: second)
            :value 1-60, default:3
        :type health_check_timeout_in_second: int
        :param health_check_interval:
            Health check interval (unit: second)
        :value 1-10, default: 3
        :type health_check_interval: int
        :param unhealth_threshold:
            The unhealthy threshold, that is, how many consecutive health
             check failures, shields the backend server.
        :value 2-5, default: 3
        :type unhealth_threshold: int
        :param health_threshold:
            Health threshold, that is, how many consecutive health checks
             are successful, then re-use the back-end server
        :value:2-5, default: 3
        :type health_threshold: int
        :param ie6_compatible:
            compatible with IE6 HTTPS request
            (the protocol format is earlier SSL3.0, the security is poor)
        :value true or false, default: true
        :type ie6_compatible: bool
        :param encryption_type:
            Encryption options, support three types:
            compatibleIE or incompatibleIE or userDefind,
            corresponding to:
            IE-compatible encryption or disabled unsecure encryption
            or custom encryption,
            when encryptionType is valid and legitimate,
            ie6Compatible field transfer value will not take effect
        type: encryption_type:string
        :param encryption_protocols:
            When the encryptionType value is userDefind,
            the list of protocol types is a string list composed of four protocols:
            "sslv3", "tlsv10", "tlsv11", "tlsv12".
        type: encryption_protocols:list
        :param dual_auth:
            Whether to Open Two-way Authentication,
            default:false
        :type dual_auth: boolean
        :param client_certIds:
            When dualAuth is true, the loaded client certificate chain
        :type client_certIds: list
        :param client_token:
            If the clientToken is not specified by the user,
            a random String generated by default algorithm will be used.
        :type client_token: string
        :param config:
        :type config: baidubce.BceClientConfiguration
        :return
        :rtype baidubce.bce_response.BceResponse
        """
        path = utils.append_uri(self.version, 'blb', blb_id, 'SSLlistener')
        params = {}
        if client_token is None:
            params[b'clientToken'] = generate_client_token()
        else:
            params[b'clientToken'] = client_token
        body = {
            'listenerPort': listener_port, 'backendPort': backend_port,
            'scheduler': compat.convert_to_string(scheduler),
            'certIds': cert_ids}
        if health_check_type is not None:
            body['healthCheckType'] = compat.convert_to_string(health_check_type)
        if server_timeout is not None:
            body['serverTimeout'] = server_timeout
        if health_check_timeout_in_second is not None:
            body['healthCheckTimeoutInSecond'] = \
                health_check_timeout_in_second
        if health_check_interval is not None:
            body['healthCheckInterval'] = health_check_interval
        if unhealth_threshold is not None:
            body['unhealthyThreshold'] = unhealth_threshold
        if health_threshold is not None:
            body['healthyThreshold'] = health_threshold
        if ie6_compatible is not None:
            body['ie6Compatible'] = ie6_compatible
        if encryption_type is not None:
            body['encryptionType'] = \
                compat.convert_to_string(encryption_type)
        if encryption_protocols is not None:
            body['encryptionProtocols'] = encryption_protocols
        if applied_ciphers is not None:
            body['appliedCiphers'] = compat.convert_to_string(applied_ciphers)
        if dual_auth is not None:
            body['dualAuth'] = dual_auth
        if client_certIds is not None:
            body['clientCertIds'] = client_certIds
        return self._send_request(http_methods.POST, path,
                                  body=json.dumps(body),
                                  params=params, config=config)

    @required(blb_id=(bytes, str))
    def describe_tcp_listener(self, blb_id, listener_port=None,
                              marker=None, max_keys=None, config=None):
        """
        get tcp listeners identified by blbID

        :param blb_id
             the id of blb which the listener work on
        :type blb_id:string

        :param listener_port
             The listener port to query
        :type listener_port:int

        :param marker
            The optional parameter marker specified in the
            original request to specify
            where in the results to begin listing.
            Together with the marker, specifies the list result
            which listing should begin.
            If the marker is not specified, the list result will
            listing from the first one.
        :type marker: string

        :param max_keys
            The optional parameter to specifies the max number of
            list result to return.
            The default value is 1000.
        :type max_keys: int

        :param config:
        :type config: baidubce.BceClientConfiguration

        :return:
        :rtype baidubce.bce_response.BceResponse
        """
        path = utils.append_uri(self.version, 'blb', blb_id, 'TCPlistener')
        params = {}

        if listener_port is not None:
            params[b'listenerPort'] = listener_port
        if marker is not None:
            params[b'marker'] = marker
        if max_keys is not None:
            params[b'maxKeys'] = max_keys

        return self._send_request(http_methods.GET, path,
                                  params=params, config=config)

    @required(blb_id=(bytes, str))
    def describe_udp_listener(self, blb_id, listener_port=None, marker=None,
                              max_keys=None, config=None):
        """
        get udp listeners identified by blbID

        :param blb_id
             the id of blb which the listener work on
        :type blb_id:string

        :param listener_port
             The listener port to query
        :type listener_port:int

        :param marker
            The optional parameter marker specified in the original
            request to specify where in the results to begin listing.
            Together with the marker, specifies the list result which
            listing should begin.
            If the marker is not specified, the list result will
            listing from the first one.
        :type marker: string

        :param max_keys
        The optional parameter to specifies the max number of
        list result to return.
            The default value is 1000.
        :type max_keys: int

        :param config:
        :type config: baidubce.BceClientConfiguration

        :return:
        :rtype baidubce.bce_response.BceResponse
        """
        path = utils.append_uri(self.version, 'blb', blb_id, 'UDPlistener')
        params = {}

        if listener_port is not None:
            params[b'listenerPort'] = listener_port
        if marker is not None:
            params[b'marker'] = marker
        if max_keys is not None:
            params[b'maxKeys'] = max_keys

        return self._send_request(http_methods.GET, path,
                                  params=params, config=config)

    @required(blb_id=(bytes, str))
    def describe_http_listener(self, blb_id, listener_port=None,
                               marker=None, max_keys=None, config=None):
        """
        get http listeners identified by blbID

        :param blb_id
             the id of blb which the listener work on
        :type blb_id:string

        :param listener_port
             The listener port to query
        :type listener_port:int

        :param marker
            The optional parameter marker specified in the original
            request to specify where in the results to begin listing.
            Together with the marker, specifies the list result which
            listing should begin.
            If the marker is not specified, the list result will listing
            from the first one.
        :type marker: string

        :param max_keys
            The optional parameter to specifies the max number of list
            result to return.
            The default value is 1000.
        :type max_keys: int

        :param config:
        :type config: baidubce.BceClientConfiguration

        :return:
        :rtype baidubce.bce_response.BceResponse
        """
        path = utils.append_uri(self.version, 'blb', blb_id, 'HTTPlistener')
        params = {}

        if listener_port is not None:
            params[b'listenerPort'] = listener_port
        if marker is not None:
            params[b'marker'] = marker
        if max_keys is not None:
            params[b'maxKeys'] = max_keys

        return self._send_request(http_methods.GET, path,
                                  params=params, config=config)

    @required(blb_id=(bytes, str))
    def describe_https_listener(self, blb_id, listener_port=None,
                                marker=None, max_keys=None, config=None):
        """
        get https listeners identified by blbID

        :param blb_id
             the id of blb which the listener work on
        :type blb_id:string

        :param listener_port
             The listener port to query
        :type listener_port:int

        :param marker
            The optional parameter marker specified in the original
            request to specify where in the results to begin listing.
            Together with the marker, specifies the list result which
            listing should begin.
            If the marker is not specified, the list result will listing
            from the first one.
        :type marker: string

        :param max_keys
            The optional parameter to specifies the max number of list
            result to return.
            The default value is 1000.
        :type max_keys: int

        :param config:
        :type config: baidubce.BceClientConfiguration

        :return:
        :rtype baidubce.bce_response.BceResponse
        """
        path = utils.append_uri(self.version, 'blb', blb_id, 'HTTPSlistener')
        params = {}

        if listener_port is not None:
            params[b'listenerPort'] = listener_port
        if marker is not None:
            params[b'marker'] = marker
        if max_keys is not None:
            params[b'maxKeys'] = max_keys

        return self._send_request(http_methods.GET, path,
                                  params=params, config=config)

    @required(blb_id=(bytes, str))
    def describe_ssl_listener(self, blb_id, listener_port=None,
                              marker=None, max_keys=None, config=None):
        """
        get ssl listeners identified by blbID

        :param blb_id
             the id of blb which the listener work on
        :type blb_id:string

        :param listener_port
             The listener port to query
        :type listener_port:int

        :param marker
            The optional parameter marker specified in the original
            request to specify where in the results to begin listing.
            Together with the marker, specifies the list result which
            listing should begin.
            If the marker is not specified, the list result will listing
            from the first one.
        :type marker: string

        :param max_keys
            The optional parameter to specifies the max number of list
            result to return.
            The default value is 1000.
        :type max_keys: int

        :param config:
        :type config: baidubce.BceClientConfiguration

        :return:
        :rtype baidubce.bce_response.BceResponse
        """
        path = utils.append_uri(self.version, 'blb', blb_id, 'SSLlistener')
        params = {}

        if listener_port is not None:
            params[b'listenerPort'] = listener_port
        if marker is not None:
            params[b'marker'] = marker
        if max_keys is not None:
            params[b'maxKeys'] = max_keys

        return self._send_request(http_methods.GET, path,
                                  params=params, config=config)

    @required(blb_id=(bytes, str))
    def describe_all_listeners(self, blb_id, listener_port=None,
                               marker=None, max_keys=None, config=None):
        """
        get all listeners identified by blbID

        :param blb_id
             the id of blb which the listener work on
        :type blb_id:string

        :param listener_port
             The listener port to query
        :type listener_port:int

        :param marker
            The optional parameter marker specified in the original
            request to specify where in the results to begin listing.
            Together with the marker, specifies the list result which
            listing should begin.
            If the marker is not specified, the list result will listing
            from the first one.
        :type marker: string

        :param max_keys
            The optional parameter to specifies the max number of list
            result to return.
            The default value is 1000.
        :type max_keys: int

        :param config:
        :type config: baidubce.BceClientConfiguration

        :return:
        :rtype baidubce.bce_response.BceResponse
        """
        path = utils.append_uri(self.version, 'blb', blb_id, 'listener')
        params = {}

        if listener_port is not None:
            params[b'listenerPort'] = listener_port
        if marker is not None:
            params[b'marker'] = marker
        if max_keys is not None:
            params[b'maxKeys'] = max_keys

        return self._send_request(http_methods.GET, path,
                                  params=params, config=config)

    @required(blb_id=(bytes, str),
              listener_port=int)
    def update_tcp_listener(self, blb_id, listener_port,
                            backend_port=None, scheduler=None,
                            health_check_type=None,
                            tcp_session_timeout=None,
                            health_check_timeout_in_second=None,
                            health_check_interval=None,
                            unhealth_threshold=None,
                            health_threshold=None,
                            config=None):
        """
        update a tcp listener rule with the specified options.

        :param blb_id:
            the id of blb which the listener work on
        :type blb_id:string

        :param listener_port:
             port to be linstened owned by listener
        :value 1-65535
        :type listener_port:int

        :param backend_port:
            port to be listened owned by Backend server
        :value 1-65535
        :type backend_port:int

        :param scheduler
            balancing algorithm
        :value 'RoundRobin'or'LeastConnection'or'Hash'
        :type scheduler:string

        :param health_check_timeout_in_second
            Health check timeout
        :value 1-60  default:3 unit:seconds
        :type health_check_timeout_in_second:string

        :param health_check_interval
            Health check interval
        :value 1-10 default:3 unit:seconds
        :type health_check_interval:string

        :param unhealth_threshold
            Unhealthy threshold,
             how many consecutive health check failures,
             shielding the backend server
        :value 2-5 default:3
        :type unhealth_threshold:string

        :param health_threshold
            Health threshold,
            how many consecutive health checks are successful,
            then re-use the back-end server
        :value 2-5 default:3
        :type health_threshold:string

         :param config:
        :type config: baidubce.BceClientConfiguration

        :return:
        :rtype baidubce.bce_response.BceResponse
        """
        path = utils.append_uri(self.version, 'blb', blb_id, 'TCPlistener')
        params = {}

        params[b'listenerPort'] = listener_port

        body = {}
        if backend_port is not None:
            body['backendPort'] = backend_port
        if scheduler is not None:
            body['scheduler'] = compat.convert_to_string(scheduler)
        if health_check_type is not None:
            body['healthCheckType'] = compat.convert_to_string(health_check_type)
        if tcp_session_timeout is not None:
            body['tcpSessionTimeout'] = tcp_session_timeout
        if health_check_timeout_in_second is not None:
            body['healthCheckTimeoutInSecond'] = \
                health_check_timeout_in_second
        if health_check_interval is not None:
            body['healthCheckInterval'] = health_check_interval
        if unhealth_threshold is not None:
            body['unhealthyThreshold'] = unhealth_threshold
        if health_threshold is not None:
            body['healthyThreshold'] = health_threshold

        return self._send_request(http_methods.PUT, path,
                                  body=json.dumps(body), params=params,
                                  config=config)

    @required(blb_id=(bytes, str),
              listener_port=int)
    def update_udp_listener(self, blb_id, listener_port, backend_port=None,
                            scheduler=None, 
                            health_check_type=None,
                            health_check_port=None,
                            health_check_string=None,
                            health_check_timeout_in_second=None,
                            health_check_interval=None,
                            unhealth_threshold=None,
                            health_threshold=None,
                            udp_session_timeout=None,
                            config=None):
        """
        update a udp listener rule with the specified options.

        :param blb_id:
                the id of blb which the listener work on
        :type blb_id:string

        :param listener_port:
                port to be linstened owned by listener
        :value 1-65535
        :type listener_port:int

        :param backend_port:
                port to be listened owned by Backend server
        :value 1-65535
        :type backend_port:int

        :param scheduler
              balancing algorithm
        :value 'RoundRobin'or'LeastConnection'or'Hash'
        :type scheduler:string

        :param health_check_type
              Health check protocol
        :value 'UDP' or 'ICMP'
        :type health_check_type:string

        :param health_check_port
              Health check port, the default is the same as backend_port.
              This field can only be updated if health_check_type is UDP.
        :type health_check_port:int

        :param health_check_string
              The request string sent by the health,
              the backend server needs to respond after receiving it,
              and supports standard escaping
        :type health_check_string:string

        :param health_check_timeout_in_second
                Health check timeout
        :value 1-60  default:3 unit:seconds
        :type health_check_timeout_in_second:string

        :param health_check_interval
                Health check interval
        :value 1-10 default:3 unit:seconds
        :type health_check_interval:string

        :param unhealth_threshold
                Unhealthy threshold,
                 how many consecutive health check failures,
                 shielding the backend server
        :value 2-5 default:3
        :type unhealth_threshold:string

        :param health_threshold
                Health threshold,
                how many consecutive health checks are successful,
                then re-use the back-end server
        :value 2-5 default:3
        :type health_threshold:string

         :param config:
        :type config: baidubce.BceClientConfiguration

        :return:
        :rtype baidubce.bce_response.BceResponse
        """
        path = utils.append_uri(self.version, 'blb', blb_id, 'UDPlistener')
        params = {}

        params[b'listenerPort'] = listener_port

        body = {}
        if backend_port is not None:
            body['backendPort'] = backend_port
        if scheduler is not None:
            body['scheduler'] = compat.convert_to_string(scheduler)
        if health_check_type is not None:
            body['healthCheckType'] = \
                compat.convert_to_string(health_check_type)
        if health_check_port is not None:
            body['healthCheckPort'] = health_check_port
        if health_check_string is not None:
            body['healthCheckString'] = \
                compat.convert_to_string(health_check_string)
        if health_check_timeout_in_second is not None:
            body['healthCheckTimeoutInSecond'] = \
                health_check_timeout_in_second
        if health_check_interval is not None:
            body['healthCheckInterval'] = health_check_interval
        if unhealth_threshold is not None:
            body['unhealthyThreshold'] = unhealth_threshold
        if health_threshold is not None:
            body['healthyThreshold'] = health_threshold
        if udp_session_timeout is not None:
            body['udpSessionTimeout'] = udp_session_timeout

        return self._send_request(http_methods.PUT, path,
                                  body=json.dumps(body),
                                  params=params, config=config)

    @required(blb_id=(bytes, str),
              listener_port=int)
    def update_http_listener(self, blb_id, listener_port, backend_port=None,
                             scheduler=None, keep_session=None,
                             keep_session_type=None,
                             keep_session_duration=None,
                             keep_session_cookie_name=None,
                             x_forward_for=None,
                             x_forwarded_proto=None,
                             additional_attributes=None,
                             health_check_type=None, health_check_port=None,
                             health_check_uri=None,
                             health_check_timeout_in_second=None,
                             health_check_interval=None,
                             unhealth_threshold=None, health_threshold=None,
                             health_check_normal_status=None,
                             health_check_host=None,
                             server_timeout=None,
                             redirect_port=None, config=None):
        """
        update a http listener rule with the specified options.
        :param blb_id:
            The id of blb which the listener work on
        :type blb_id: string
        :param listener_port:
            Port to be linstened owned by listener
        :value 1-65535
        :type listener_port: int
        :param backend_port:
            port to be listened owned by Backend server
        :value 1-65535
        :type backend_port: int
        :param scheduler:
            Balancing algorithm
        :value 'RoundRobin' or 'LeastConnection' or 'Hash'
        :type scheduler: string
        :param keep_session:
            Whether to enable the session hold function, that is,
            the request sent by the same client will reach the
            same backend server
        :value true or false, default:false
        :type keep_session: bool
        :param keep_session_type:
            The cookie handling method maintained by the session,
            valid only if the session is held open
        :value 'insert' or 'rewrite', default:insert
        :type keep_session_type: string
        :param keep_session_duration:
            The time the cookie is kept in session (in seconds),
            valid only if the session is held open
        :value 1-15552000, default:3600
        :type keep_session_duration: int
        :param keep_session_cookie_name:
            The session keeps the name of the cookie that needs
            to be overridden,if and only if session persistence is
            enabled and keep_session_type="rewrite"
        :type keep_session_cookie_name: int
        :param x_forward_for:
            Whether to enable the real IP address of the client,
            the backend server can obtain the real address of the
            client through the X-Forwarded-For HTTP header.
        :value true or false, default: flase
        :type x_forward_for: bool
        :param health_check_type:
            Health check protocol
        :value 'HTTP' or 'TCP'
        :type health_check_type: string
        :param health_check_port:
            Health check port, the default is the same as backend_port
        :type health_check_port: int
        :param health_check_uri:
            Health check URI, default '/'.
            Effective when the health check protocol is "HTTP"
        :type health_check_uri: string
        :param health_check_timeout_in_second:
            Health check timeout (unit: second)
        :value 1-60, default: 3
        :type health_check_timeout_in_second: int
        :param health_check_interval:
            Health check interval (unit: second)
        :value 1-10, default: 3
        :type health_check_interval: int
        :param unhealth_threshold:
            The unhealthy threshold, that is, how many consecutive health
            check failures, shields the backend server.
        :value 2-5, default: 3
        :type unhealth_threshold: int
        :param health_threshold:
            Health threshold, that is, how many consecutive health checks
            are successful, then re-use the back-end server
        :value:2-5, default: 3
        :type health_threshold: int
        :param health_check_normal_status:
            The HTTP status code when the health check is normal supports
            a combination of five types of status codes,
            such as "http_1xx|http_2xx", Effective when the health check
            protocol is "HTTP"
        :value default: http_2xx|http_3xx
        :type health_check_normal_status: string
        :param server_timeout:
            Backend server maximum timeout (unit: second)
        :value 1-3600, default: 30
        :type server_timeout: int
        :param redirect_port:
            Forward the request received by this listener to the HTTPS
            listener, which is specified by the HTTPS listener.
        :type redirect_port: int
        :param config:
        :type config: baidubce.BceClientConfiguration
        :return:
        :rtype baidubce.bce_response.BceResponse
        """
        path = utils.append_uri(self.version, 'blb', blb_id, 'HTTPlistener')
        params = {}
        params[b'listenerPort'] = listener_port

        body = {}
        if backend_port is not None:
            body['backendPort'] = backend_port
        if scheduler is not None:
            body['scheduler'] = compat.convert_to_string(scheduler)
        if keep_session is not None:
            body['keepSession'] = keep_session
        if keep_session_type is not None:
            body['keepSessionType'] = \
                compat.convert_to_string(keep_session_type)
        if keep_session_duration is not None:
            body['keepSessionDuration'] = keep_session_duration
        if keep_session_cookie_name is not None:
            body['keepSessionCookieName'] = keep_session_cookie_name
        if x_forward_for is not None:
            body['xForwardFor'] = x_forward_for
        if x_forwarded_proto is not None:
            body['xForwardedProto'] = x_forwarded_proto
        if additional_attributes is not None:
            body['additionalAttributes'] = additional_attributes
        if health_check_type is not None:
            body['healthCheckType'] = \
                compat.convert_to_string(health_check_type)
        if health_check_port is not None:
            body['healthCheckPort'] = health_check_port
        if health_check_uri is not None:
            body['healthCheckURI'] = \
                compat.convert_to_string(health_check_uri)
        if health_check_timeout_in_second is not None:
            body['healthCheckTimeoutInSecond'] = \
                health_check_timeout_in_second
        if health_check_interval is not None:
            body['healthCheckInterval'] = health_check_interval
        if unhealth_threshold is not None:
            body['unhealthyThreshold'] = unhealth_threshold
        if health_threshold is not None:
            body['healthyThreshold'] = health_threshold
        if health_check_normal_status is not None:
            body['healthCheckNormalStatus'] = \
                compat.convert_to_string(health_check_normal_status)
        if health_check_host is not None:
            body['healthCheckHost'] = compat.convert_to_string(health_check_host)
        if server_timeout is not None:
            body['serverTimeout'] = server_timeout
        if redirect_port is not None:
            body['redirectPort'] = redirect_port
        return self._send_request(http_methods.PUT, path,
                                  body=json.dumps(body),
                                  params=params, config=config)

    @required(blb_id=(bytes, str), listener_port=int)
    def update_https_listener(self, blb_id, listener_port,
                              backend_port=None,
                              scheduler=None, keep_session=None,
                              keep_session_type=None,
                              keep_session_duration=None,
                              keep_session_cookie_name=None,
                              x_forward_for=None,
                              x_forwarded_proto=None,
                              additional_attributes=None,
                              health_check_type=None,
                              health_check_port=None, health_check_uri=None,
                              health_check_timeout_in_second=None,
                              health_check_interval=None,
                              unhealth_threshold=None, health_threshold=None,
                              health_check_normal_status=None,
                              health_check_host=None,
                              server_timeout=None,
                              cert_ids=None, additional_cert_domains=None,
                              ie6_compatible=None,
                              encryption_type=None, encryption_protocols=None,
                              applied_ciphers=None,
                              config=None):
        """
        update a https listener rule with the specified options.
        :param blb_id:
            The id of blb which the listener work on
        :type blb_id: string
        :param listener_port:
            Port to be linstened owned by listener
        :value 1-65535
        :type listener_port: int
        :param backend_port:
            Port to be listened owned by Backend server
        :value 1-65535
        :type backend_port: int
        :param scheduler:
            Balancing algorithm
        :value 'RoundRobin' or 'LeastConnection' or 'Hash'
        :type scheduler: string
        :param keep_session:
            Whether to enable the session hold function, that is, the request
            sent by the same client will reach the same backend server
        :value true or false, default: false
        :type keep_session: bool
        :param keep_session_type:
            The cookie handling method maintained by the session,
            valid only if the session is held open
        :value 'insert' or 'rewrite', default: insert
        :type keep_session_type: string
        :param keep_session_duration:
            The time the cookie is kept in session (in seconds),
            valid only if the session is held open
        :value 1-15552000, default:3600
        :type keep_session_duration: int
        :param keep_session_cookie_name:
            The session keeps the name of the cookie that needs to be
            overridden,if and only if session persistence is enabled and
            keep_session_type="rewrite"
        :type keep_session_cookie_name: int
        :param x_forward_for:
            Whether to enable the real IP address of the client,
            the backend server can obtain the real address of the client
            through the X-Forwarded-For HTTP header.
        :value true or false, default: False
        :type x_forward_for: bool
        :param health_check_type:
            Health check protocol
        :value 'HTTP' or 'TCP'
        :type health_check_type: string
        :param health_check_port:
            Health check port, the default is the same as backend_port
        :type health_check_port: int
        :param health_check_uri:
            Health check URI, default '/'.
            Effective when the health check protocol is "HTTP"
        :type health_check_uri: string
        :param health_check_timeout_in_second:
            Health check timeout (unit: second)
        :value 1-60, default: 3
        :type health_check_timeout_in_second: int
        :param health_check_interval:
            Health check interval (unit: second)
        :value 1-10, default: 3
        :type health_check_interval: int
        :param unhealth_threshold:
            The unhealthy threshold, that is, how many consecutive health
            check failures, shields the backend server.
        :value 2-5, default: 3
        :type unhealth_threshold: int
        :param health_threshold:
            Health threshold, that is, how many consecutive health checks
            are successful, then re-use the back-end server
        :value:2-5, default: 3
        :type health_threshold: int
        :param health_check_normal_status:
            The HTTP status code when the health check is normal supports
            a combination of five types of status codes,
            such as "http_1xx|http_2xx", Effective when the health check
            protocol is "HTTP"
        :value default: http_2xx|http_3xx
        :type health_check_normal_status: string
        :param server_timeout:
            Backend server maximum timeout (unit: second)
        :value 1-3600, default: 30
        :type server_timeout: int
        :param cert_ids:
            The SSL certificate to be loaded by the listener.
            Currently HTTPS listeners can only bind one SSL certificate.
        :type cert_ids:List<String>
        :param: additional_cert_domains:
            Additional domain name,each element is an object that contains two attributes, namely "cert_id" and "host"
        :type additional_cert_domains: list
        :param ie6_compatible:
            Is it compatible with IE6 HTTPS request
            (the protocol format is earlier SSL3.0, the security is poor)
        :value true or false, default: true
        :type ie6_compatible: bool
        :param config:
        :type config: baidubce.BceClientConfiguration
        :return:
        :rtype baidubce.bce_response.BceResponse
        """
        path = utils.append_uri(self.version, 'blb', blb_id, 'HTTPSlistener')
        params = {}
        params[b'listenerPort'] = listener_port
        body = {}
        if backend_port is not None:
            body['backendPort'] = backend_port
        if scheduler is not None:
            body['scheduler'] = compat.convert_to_string(scheduler)
        if keep_session is not None:
            body['keepSession'] = keep_session
        if keep_session_type is not None:
            body['keepSessionType'] = \
                compat.convert_to_string(keep_session_type)
        if keep_session_duration is not None:
            body['keepSessionDuration'] = keep_session_duration
        if keep_session_cookie_name is not None:
            body['keepSessionCookieName'] = keep_session_cookie_name
        if x_forward_for is not None:
            body['xForwardFor'] = x_forward_for
        if x_forwarded_proto is not None:
            body['xForwardedProto'] = x_forwarded_proto
        if additional_attributes is not None:
            body['additionalAttributes'] = additional_attributes
        if health_check_type is not None:
            body['healthCheckType'] = \
                compat.convert_to_string(health_check_type)
        if health_check_port is not None:
            body['healthCheckPort'] = health_check_port
        if health_check_uri is not None:
            body['healthCheckURI'] = \
                compat.convert_to_string(health_check_uri)
        if health_check_timeout_in_second is not None:
            body['healthCheckTimeoutInSecond'] = \
                health_check_timeout_in_second
        if health_check_interval is not None:
            body['healthCheckInterval'] = health_check_interval
        if unhealth_threshold is not None:
            body['unhealthyThreshold'] = unhealth_threshold
        if health_threshold is not None:
            body['healthyThreshold'] = health_threshold
        if health_check_normal_status is not None:
            body['healthCheckNormalStatus'] = \
                compat.convert_to_string(health_check_normal_status)
        if health_check_host is not None:
            body['healthCheckHost'] = compat.convert_to_string(health_check_host)
        if server_timeout is not None:
            body['serverTimeout'] = server_timeout
        if cert_ids is not None:
            body['certIds'] = cert_ids
        if additional_cert_domains is not None:
            body['additionalCertDomains'] = additional_cert_domains
        if ie6_compatible is not None:
            body['ie6Compatible'] = ie6_compatible
        if encryption_type is not None:
            body['encryptionType'] = compat.convert_to_string(encryption_type)
        if encryption_protocols is not None:
            body['encryptionProtocols'] = encryption_protocols
        if applied_ciphers is not None:
            body['appliedCiphers'] = compat.convert_to_string(applied_ciphers)
        return self._send_request(http_methods.PUT, path,
                                  body=json.dumps(body), params=params,
                                  config=config)

    @required(blb_id=(bytes, str), listener_port=int)
    def update_ssl_listener(self, blb_id, listener_port,
                            backend_port=None, scheduler=None,
                            health_check_type=None,
                            health_check_timeout_in_second=None,
                            health_check_interval=None,
                            unhealth_threshold=None,
                            health_threshold=None, cert_ids=None,
                            ie6_compatible=None,
                            encryption_type=None,
                            encryption_protocols=None,
                            applied_ciphers=None,
                            dual_auth=None, client_certIds=None,
                            config=None):
        """
        update a ssl listener rule with the specified options.
        :param blb_id:
            The id of blb which the listener work on
        :type blb_id: string
        :param listener_port:
            port to be linstened owned by listener
        :value 1-65535
        :type listener_port: int
        :param backend_port:
            Port to be listened owned by Backend server
        :value 1-65535
        :type backend_port: int
        :param scheduler:
            balancing algorithm
        :value 'RoundRobin' or 'LeastConnection'
        :type scheduler: string
        :param health_check_timeout_in_second:
            Health check timeout (unit: second)
            :value 1-60, default:3
        :type health_check_timeout_in_second: int
        :param health_check_interval:
            Health check interval (unit: second)
        :value 1-10, default: 3
        :type health_check_interval: int
        :param unhealth_threshold:
            The unhealthy threshold, that is, how many consecutive health
             check failures, shields the backend server.
        :value 2-5, default: 3
        :type unhealth_threshold: int
        :param health_threshold:
            Health threshold, that is, how many consecutive health checks
             are successful, then re-use the back-end server
        :value:2-5, default: 3
        :type health_threshold: int
        :param cert_ids:
            The SSL certificate to be loaded by the listener.
            Currently HTTPS listeners can only bind one SSL certificate.
        :type cert_ids: List<String>
        :param ie6_compatible:
            compatible with IE6 HTTPS request
            (the protocol format is earlier SSL3.0, the security is poor)
        :value true or false, default: true
        :type ie6_compatible: bool
        :param encryption_type:
            Encryption options, support three types:
            compatibleIE or incompatibleIE or userDefind,
            corresponding to:
            IE-compatible encryption or disabled unsecure encryption or
            custom encryption,
            when encryptionType is valid and legitimate,
            ie6Compatible field transfer value will not take effect
        type: encryption_type:string
        :param encryption_protocols:
            When the encryptionType value is userDefind,
            the list of protocol types is a string list composed of four protocols:
            "sslv3", "tlsv10", "tlsv11", "tlsv12".
        type: encryption_protocols:list
        :param dual_auth:
            Whether to Open Two-way Authentication,
            default:false
        :type dual_auth: boolean
        :param client_certIds:
            When dualAuth is true, the loaded client certificate chain
        :type client_certIds: list
        :param config:
        :type config: baidubce.BceClientConfiguration
        :return
        :rtype baidubce.bce_response.BceResponse
        """
        path = utils.append_uri(self.version, 'blb', blb_id, 'SSLlistener')
        params = {}
        params[b'listenerPort'] = listener_port
        body = {}
        if backend_port is not None:
            body['backendPort'] = backend_port
        if scheduler is not None:
            body['scheduler'] = compat.convert_to_string(scheduler)
        if health_check_type is not None:
            body['healthCheckType'] = compat.convert_to_string(health_check_type)
        if health_check_timeout_in_second is not None:
            body['healthCheckTimeoutInSecond'] = \
                health_check_timeout_in_second
        if health_check_interval is not None:
            body['healthCheckInterval'] = health_check_interval
        if unhealth_threshold is not None:
            body['unhealthyThreshold'] = unhealth_threshold
        if health_threshold is not None:
            body['healthyThreshold'] = health_threshold
        if cert_ids is not None:
            body['certIds'] = cert_ids
        if ie6_compatible is not None:
            body['ie6Compatible'] = ie6_compatible
        if encryption_type is not None:
            body['encryptionType'] = \
                compat.convert_to_string(encryption_type)
        if encryption_protocols is not None:
            body['encryptionProtocols'] = encryption_protocols
        if applied_ciphers is not None:
            body['appliedCiphers'] = compat.convert_to_string(applied_ciphers)
        if dual_auth is not None:
            body['dualAuth'] = dual_auth
        if client_certIds is not None:
            body['clientCertIds'] = client_certIds
        return self._send_request(http_methods.PUT, path,
                                  body=json.dumps(body),
                                  params=params, config=config)

    @required(blb_id=(bytes, str))
    def delete_listeners(self, blb_id, port_list=None, port_type_list=None,
                         client_token=None, config=None):
        """
        Release the listener under the specified LoadBalancer,
        the listener is specified by listening to the port.

        :param blb_id:
            id of LoadBalancer
        :type blb_id: string

        :param port_list:
            The ports of listeners to be released.
            Use this parameter to delete listeners by port only.
        :type port_list: list<int>

        :param port_type_list:
            List of port and type pairs to release listeners with protocol specification.
            Each element should be a dict with 'port' (int) and 'type' (str) keys.
            Use this parameter when same port has multiple protocols and you want to
            delete a specific protocol listener.
            Example: [{'port': 80, 'type': 'TCP'}, {'port': 80, 'type': 'UDP'}]
            Note: port_list and port_type_list should pass at least one.
        :type port_type_list: list<dict>

        :param client_token:
            If the clientToken is not specified by the user, a random String
            generated by default algorithm will be used.
        :type client_token: string

        :param config:
        :type config: baidubce.BceClientConfiguration

        :return:
        :rtype baidubce.bce_response.BceResponse
        """
        path = utils.append_uri(self.version, 'blb', blb_id, 'listener')
        params = {}

        params[b'batchdelete'] = None

        if client_token is None:
            params[b'clientToken'] = generate_client_token()
        else:
            params[b'clientToken'] = client_token

        body = {}
        if port_list is not None:
            body['portList'] = port_list
        if port_type_list is not None:
            body['portTypeList'] = port_type_list

        return self._send_request(http_methods.PUT, path,
                                  body=json.dumps(body), params=params,
                                  config=config)

    """
        BackendServer API
    """

    @required(blb_id=(bytes, str),
              backend_server_list=list)
    def add_backend_servers(self, blb_id, backend_server_list,
                            client_token=None, config=None):
        """
        Add a backend server for the specified LoadBalancer,
        support batch add

        :param blb_id:
                id of LoadBalancer
        :type blb_id:string

        :param backend_server_list
                List of backend servers to be added
        :type backend_server_list:List<BackendServerModel>
        BackendServerModel{:param:instanceId
                               id of  Backend server
                           :type instanceId:string

                           :param weight
                               Backend server weight, value range [0, 100],
                               weight 0 means not to forward traffic to
                               the backend server
                           :type weight:int
                          }

        :param client_token:
            If the clientToken is not specified by the user, a random String
            generated by default algorithm will be used.
        :type client_token: string

        :param config:
        :type config: baidubce.BceClientConfiguration

        :return:
        :rtype baidubce.bce_response.BceResponse
        """
        path = utils.append_uri(self.version, 'blb', blb_id, 'backendserver')
        params = {}

        if client_token is None:
            params[b'clientToken'] = generate_client_token()
        else:
            params[b'clientToken'] = client_token

        body = {}

        body['backendServerList'] = backend_server_list

        return self._send_request(http_methods.POST, path,
                                  body=json.dumps(body), params=params,
                                  config=config)

    @required(blb_id=(bytes, str),
              listener_port=int)
    def describe_health_status(self, blb_id, listener_port,
                               marker=None, max_keys=None, config=None):
        """
        Query the information about the backend server under the specified
        LoadBalancer identified by listenPort

        :param blb_id:
            id of LoadBalancer
        :type blb_id: string

        :param listener_port:
            port to be linstened owned by listener
        :value 1-65535
        :type listener_port: int

        :param marker:
            The optional parameter marker specified in the original request
            to specify where in the results to begin listing.
            Together with the marker, specifies the list result which listing
            should begin. If the marker is not specified, the list result will
            listing from the first one.
        :type marker: string

        :param max_keys:
            The optional parameter to specifies the max number of list
            result to return.
            The default value is 1000.
        :type max_keys: int

        :param config:
        :type config: baidubce.BceClientConfiguration

        :return:
        :rtype baidubce.bce_response.BceResponse
        """
        path = utils.append_uri(self.version, 'blb', blb_id, 'backendserver')
        params = {}

        params[b'listenerPort'] = listener_port

        if marker is not None:
            params[b'marker'] = marker
        if max_keys is not None:
            params[b'maxKeys'] = max_keys

        return self._send_request(http_methods.GET, path, params=params,
                                  config=config)

    @required(blb_id=(bytes, str))
    def describe_backend_servers(self, blb_id, marker=None,
                                 max_keys=None, config=None):
        """
        Query the list of backend servers under the specified LoadBalancer

        :param blb_id:
            Id of LoadBalancer
        :type blb_id:string

        :param marker:
            The optional parameter marker specified in the original
            request to specify where in the results to begin listing.
            Together with the marker, specifies the list result which
            listing should begin. If the marker is not specified,
            the list result will listing from the first one.
        :type marker: string

        :param max_keys:
            The optional parameter to specifies the max number of
            list result to return.
            The default value is 1000.
        :type max_keys: int

        :param config:
        :type config: baidubce.BceClientConfiguration

        :return:
        :rtype baidubce.bce_response.BceResponse
        """
        path = utils.append_uri(self.version, 'blb', blb_id, 'backendserver')
        params = {}

        if marker is not None:
            params[b'marker'] = marker
        if max_keys is not None:
            params[b'maxKeys'] = max_keys

        return self._send_request(http_methods.GET, path, params=params,
                                  config=config)

    @required(blb_id=(bytes, str),
              backend_server_list=list)
    def update_backend_servers(self, blb_id, backend_server_list,
                               client_token=None, config=None):
        """
        update the information about the backend server under
        the specified LoadBalancer

        :param blb_id:
            id of LoadBalancer
        :type blb_id:string

        :param backend_server_list:
            List of backend servers to be updated
        :type backend_server_list:List<BackendServerModel>
        BackendServerModel{:param:instanceId
                              id of  Backend server
                           :type instanceId:string

                           :param weight
                               Backend server weight, value range [0, 100],
                               weight 0 means not to forward traffic to
                               the backend server
                           :type weight:int
                          }

        :param client_token:
            If the clientToken is not specified by the user, a random String
            generated by default algorithm will be used.
        :type client_token: string

        :param config:
        :type config: baidubce.BceClientConfiguration

        :return:
        :rtype baidubce.bce_response.BceResponse
        """
        path = utils.append_uri(self.version, 'blb', blb_id, 'backendserver')
        params = {}

        params[b'update'] = None

        if client_token is None:
            params[b'clientToken'] = generate_client_token()
        else:
            params[b'clientToken'] = client_token

        body = {}
        body['backendServerList'] = backend_server_list

        return self._send_request(http_methods.PUT, path,
                                  body=json.dumps(body), params=params,
                                  config=config)

    @required(blb_id=(bytes, str),
              backend_server_list=list)
    def remove_backend_servers(self, blb_id, backend_server_list,
                               client_token=None, config=None):
        """
        Release the backend server under the specified LoadBalancer,
        which is specified by its backend server

        :param blb_id:
                id of LoadBalancer
        :type blb_id:string

        :param backend_server_list:
                List of backend servers to be removed
        :type backend_server_list:List<string>

        :param client_token:
                If the clientToken is not specified by the user,
                a random String generated by default algorithm will be used.
        :type client_token: string

        :param config:
        :type config: baidubce.BceClientConfiguration

        :return:
        :rtype baidubce.bce_response.BceResponse
        """
        path = utils.append_uri(self.version, 'blb', blb_id, 'backendserver')
        params = {}

        if client_token is None:
            params[b'clientToken'] = generate_client_token()
        else:
            params[b'clientToken'] = client_token

        body = {}
        body['backendServerList'] = backend_server_list

        return self._send_request(http_methods.PUT, path,
                                  body=json.dumps(body), params=params,
                                  config=config)

    @required(blb_id=(bytes, str),
              securitygroupids=list)
    def bind_security_groups(self, blb_id, securitygroupids,
                             client_token=None, config=None):
        """
        bind the blb security groups (normal/ipv6 LoadBalancer)

        :param blb_id:
                id of LoadBalancer
        :type blb_id:string

        :param securitygroupids:
                List of security group ids to be bind
        :type securitygroupids:List<string>

        :param client_token:
                If the clientToken is not specified by the user,
                a random String generated by default algorithm will be used.
        :type client_token: string

        :param config:
        :type config: baidubce.BceClientConfiguration

        :return:
        :rtype baidubce.bce_response.BceResponse
        """
        path = utils.append_uri(self.version, 'blb', blb_id, 'securitygroup')
        params = {}

        params[b'bind'] = None
        if client_token is None:
            params[b'clientToken'] = generate_client_token()
        else:
            params[b'clientToken'] = client_token

        body = {}
        body['securityGroupIds'] = securitygroupids
        return self._send_request(http_methods.PUT, path,
                                  body=json.dumps(body), params=params,
                                  config=config)

    @required(blb_id=(bytes, str),
              securitygroupids=list)
    def unbind_security_groups(self, blb_id, securitygroupids,
                               client_token=None, config=None):
        """
        unbind the blb security groups (normal/ipv6 LoadBalancer)

        :param blb_id:
                id of LoadBalancer
        :type blb_id:string

        :param securitygroupids:
                List of security group ids to be bind
        :type securitygroupids:List<string>

        :param client_token:
                If the clientToken is not specified by the user,
                a random String generated by default algorithm will be used.
        :type client_token: string

        :param config:
        :type config: baidubce.BceClientConfiguration

        :return:
        :rtype baidubce.bce_response.BceResponse
        """
        path = utils.append_uri(self.version, 'blb', blb_id, 'securitygroup')
        params = {}

        params[b'unbind'] = None
        if client_token is None:
            params[b'clientToken'] = generate_client_token()
        else:
            params[b'clientToken'] = client_token

        body = {}
        body['securityGroupIds'] = securitygroupids
        return self._send_request(http_methods.PUT, path,
                                  body=json.dumps(body), params=params,
                                  config=config)

    @required(blb_id=(bytes, str))
    def describe_security_groups(self, blb_id,
                                 client_token=None, config=None):
        """
        describe the blb security groups (normal/ipv6 LoadBalancer)

        :param blb_id:
                id of LoadBalancer
        :type blb_id:string

        :param client_token:
                If the clientToken is not specified by the user,
                a random String generated by default algorithm will be used.
        :type client_token: string

        :param config:
        :type config: baidubce.BceClientConfiguration

        :return:
        :rtype baidubce.bce_response.BceResponse
        """
        path = utils.append_uri(self.version, 'blb', blb_id, 'securitygroup')
        params = {}

        if client_token is None:
            params[b'clientToken'] = generate_client_token()
        else:
            params[b'clientToken'] = client_token

        return self._send_request(http_methods.GET, path, params=params,
                                  config=config)

    @required(blb_id=(bytes, str),
              enterprisesecuritygroupids=list)
    def bind_enterprise_security_groups(self, blb_id, enterprisesecuritygroupids,
                                        client_token=None, config=None):
        """
        bind the blb enterprise security groups (normal/ipv6 LoadBalancer)

        :param blb_id:
                id of LoadBalancer
        :type blb_id:string

        :param enterprisesecuritygroupids:
                List of enterprise security group ids to be bind
        :type enterprisesecuritygroupids:List<string>

        :param client_token:
                If the clientToken is not specified by the user,
                a random String generated by default algorithm will be used.
        :type client_token: string

        :param config:
        :type config: baidubce.BceClientConfiguration

        :return:
        :rtype baidubce.bce_response.BceResponse
        """
        path = utils.append_uri(self.version, 'blb', blb_id, 'enterprise', 'securitygroup')
        params = {}

        params[b'bind'] = None
        if client_token is None:
            params[b'clientToken'] = generate_client_token()
        else:
            params[b'clientToken'] = client_token

        body = {}
        body['enterpriseSecurityGroupIds'] = enterprisesecuritygroupids
        return self._send_request(http_methods.PUT, path,
                                  body=json.dumps(body), params=params,
                                  config=config)

    @required(blb_id=(bytes, str),
              enterprisesecuritygroupids=list)
    def unbind_enterprise_security_groups(self, blb_id, enterprisesecuritygroupids,
                                          client_token=None, config=None):
        """
        unbind the blb enterprise security groups (normal/ipv6 LoadBalancer)

        :param blb_id:
                id of LoadBalancer
        :type blb_id:string

        :param enterprisesecuritygroupids:
                List of enterprise security group ids to be unbind
        :type enterprisesecuritygroupids:List<string>

        :param client_token:
                If the clientToken is not specified by the user,
                a random String generated by default algorithm will be used.
        :type client_token: string

        :param config:
        :type config: baidubce.BceClientConfiguration

        :return:
        :rtype baidubce.bce_response.BceResponse
        """
        path = utils.append_uri(self.version, 'blb', blb_id, 'enterprise', 'securitygroup')
        params = {}

        params[b'unbind'] = None
        if client_token is None:
            params[b'clientToken'] = generate_client_token()
        else:
            params[b'clientToken'] = client_token

        body = {}
        body['enterpriseSecurityGroupIds'] = enterprisesecuritygroupids
        return self._send_request(http_methods.PUT, path,
                                  body=json.dumps(body), params=params,
                                  config=config)

    @required(blb_id=(bytes, str))
    def describe_enterprise_security_groups(self, blb_id,
                                            client_token=None, config=None):
        """
        describe the blb enterprise security groups (normal/ipv6 LoadBalancer)

        :param blb_id:
                id of LoadBalancer
        :type blb_id:string

        :param client_token:
                If the clientToken is not specified by the user,
                a random String generated by default algorithm will be used.
        :type client_token: string

        :param config:
        :type config: baidubce.BceClientConfiguration

        :return:
        :rtype baidubce.bce_response.BceResponse
        """
        path = utils.append_uri(self.version, 'blb', blb_id, 'enterprise', 'securitygroup')
        params = {}

        if client_token is None:
            params[b'clientToken'] = generate_client_token()
        else:
            params[b'clientToken'] = client_token

        return self._send_request(http_methods.GET, path, params=params,
                                  config=config)


def generate_client_token_by_uuid():
    """
    The default method to generate the random string for client_token
    if the optional parameter client_token is not specified by the user.

    :return:
    :rtype string
    """
    return str(uuid.uuid4())


generate_client_token = generate_client_token_by_uuid
