b54dc219c1
* Unskip related API tests * Fixed a number of negative pool tests which didn't pass listener_id with create_pool requests thus didn't actually test anything. Change-Id: If50c664086e1b2bffa2899775de010c0a424f505 Related-Bug: #1408230
633 lines
24 KiB
Python
633 lines
24 KiB
Python
# Copyright 2014 OpenStack Foundation.
|
|
# 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.
|
|
|
|
|
|
import abc
|
|
|
|
from oslo_config import cfg
|
|
from oslo_log import log as logging
|
|
import six
|
|
|
|
from neutron.api import extensions
|
|
from neutron.api.v2 import attributes as attr
|
|
from neutron.api.v2 import base
|
|
from neutron.api.v2 import resource_helper
|
|
from neutron.common import exceptions as nexception
|
|
from neutron import manager
|
|
from neutron.plugins.common import constants
|
|
from neutron.services import service_base
|
|
|
|
from neutron_lbaas.services.loadbalancer import constants as lb_const
|
|
|
|
LOADBALANCERV2_PREFIX = "/lbaas"
|
|
|
|
LOG = logging.getLogger(__name__)
|
|
|
|
|
|
# Loadbalancer Exceptions
|
|
# This exception is only for a workaround when having v1 and v2 lbaas extension
|
|
# and plugins enabled
|
|
class RequiredAttributeNotSpecified(nexception.BadRequest):
|
|
message = _("Required attribute %(attr_name)s not specified")
|
|
|
|
|
|
class EntityNotFound(nexception.NotFound):
|
|
message = _("%(name)s %(id)s could not be found")
|
|
|
|
|
|
class DelayOrTimeoutInvalid(nexception.BadRequest):
|
|
message = _("Delay must be greater than or equal to timeout")
|
|
|
|
|
|
class EntityInUse(nexception.InUse):
|
|
message = _("%(entity_using)s %(id)s is using this %(entity_in_use)s")
|
|
|
|
|
|
class OnePoolPerListener(nexception.InUse):
|
|
message = _("Only one pool per listener allowed. Listener "
|
|
"%(listener_id)s is already using Pool %(pool_id)s.")
|
|
|
|
|
|
class OneHealthMonitorPerPool(nexception.InUse):
|
|
message = _("Only one health monitor per pool allowed. Pool %(pool_id)s"
|
|
" is already using Health Monitor %(hm_id)s.")
|
|
|
|
|
|
class LoadBalancerListenerProtocolPortExists(nexception.Conflict):
|
|
message = _("Load Balancer %(lb_id)s already has a listener with "
|
|
"protocol_port of %(protocol_port)s")
|
|
|
|
|
|
class ListenerPoolProtocolMismatch(nexception.Conflict):
|
|
message = _("Listener protocol %(listener_proto)s and pool protocol "
|
|
"%(pool_proto)s are not compatible.")
|
|
|
|
|
|
class AttributeIDImmutable(nexception.NeutronException):
|
|
message = _("Cannot change %(attribute)s if one already exists")
|
|
|
|
|
|
class StateInvalid(nexception.NeutronException):
|
|
message = _("Invalid state %(state)s of loadbalancer resource %(id)s")
|
|
|
|
|
|
class MemberNotFoundForPool(nexception.NotFound):
|
|
message = _("Member %(member_id)s could not be found in pool "
|
|
"%(pool_id)s")
|
|
|
|
|
|
class MemberExists(nexception.Conflict):
|
|
message = _("Member with address %(address)s and protocol_port %(port)s "
|
|
"already present in pool %(pool)s")
|
|
|
|
|
|
class MemberAddressTypeSubnetTypeMismatch(nexception.NeutronException):
|
|
message = _("Member with address %(address)s and subnet %(subnet_id) "
|
|
"have mismatched IP versions")
|
|
|
|
|
|
class DriverError(nexception.NeutronException):
|
|
message = _("An error happened in the driver")
|
|
|
|
|
|
class LBConfigurationUnsupported(nexception.NeutronException):
|
|
message = _("Load balancer %(load_balancer_id)s configuration is not "
|
|
"supported by driver %(driver_name)s")
|
|
|
|
|
|
class SessionPersistenceConfigurationInvalid(nexception.BadRequest):
|
|
message = _("Session Persistence Invalid: %(msg)s")
|
|
|
|
|
|
class TLSDefaultContainerNotSpecified(nexception.BadRequest):
|
|
message = _("Default TLS container was not specified")
|
|
|
|
|
|
class TLSContainerNotFound(nexception.NotFound):
|
|
message = _("TLS container %(container_id)s could not be found")
|
|
|
|
|
|
class TLSContainerInvalid(nexception.NeutronException):
|
|
message = _("TLS container %(container_id)s is invalid. %(reason)s")
|
|
|
|
|
|
class CertManagerError(nexception.NeutronException):
|
|
message = _("Could not process TLS container %(ref)s, %(reason)s")
|
|
|
|
|
|
class ProviderFlavorConflict(nexception.Conflict):
|
|
message = _("Cannot specify both a flavor and a provider")
|
|
|
|
|
|
class FlavorsPluginNotLoaded(nexception.NotFound):
|
|
message = _("Flavors plugin not found")
|
|
|
|
|
|
def _validate_connection_limit(data, min_value=lb_const.MIN_CONNECT_VALUE):
|
|
if int(data) < min_value:
|
|
msg = (_("'%(data)s' is not a valid value, "
|
|
"because it cannot be less than %(min_value)s") %
|
|
{'data': data, 'min_value': min_value})
|
|
LOG.debug(msg)
|
|
return msg
|
|
|
|
attr.validators['type:connection_limit'] = _validate_connection_limit
|
|
|
|
|
|
RESOURCE_ATTRIBUTE_MAP = {
|
|
'loadbalancers': {
|
|
'id': {'allow_post': False, 'allow_put': False,
|
|
'validate': {'type:uuid': None},
|
|
'is_visible': True,
|
|
'primary_key': True},
|
|
'name': {'allow_post': True, 'allow_put': True,
|
|
'validate': {'type:string': attr.NAME_MAX_LEN},
|
|
'default': '',
|
|
'is_visible': True},
|
|
'tenant_id': {'allow_post': True, 'allow_put': False,
|
|
'validate': {'type:not_empty_string':
|
|
attr.TENANT_ID_MAX_LEN},
|
|
'required_by_policy': True,
|
|
'is_visible': True},
|
|
'description': {'allow_post': True, 'allow_put': True,
|
|
'validate': {'type:string': attr.DESCRIPTION_MAX_LEN},
|
|
'is_visible': True, 'default': ''},
|
|
'vip_subnet_id': {'allow_post': True, 'allow_put': False,
|
|
'validate': {'type:uuid': None},
|
|
'is_visible': True},
|
|
'vip_address': {'allow_post': True, 'allow_put': False,
|
|
'default': attr.ATTR_NOT_SPECIFIED,
|
|
'validate': {'type:ip_address_or_none': None},
|
|
'is_visible': True},
|
|
'vip_port_id': {'allow_post': False, 'allow_put': False,
|
|
'is_visible': True},
|
|
'provider': {'allow_post': True, 'allow_put': False,
|
|
'validate': {'type:string': None},
|
|
'is_visible': True, 'default': attr.ATTR_NOT_SPECIFIED},
|
|
'listeners': {'allow_post': False, 'allow_put': False,
|
|
'is_visible': True},
|
|
'admin_state_up': {'allow_post': True, 'allow_put': True,
|
|
'default': True,
|
|
'convert_to': attr.convert_to_boolean,
|
|
'is_visible': True},
|
|
'provisioning_status': {'allow_post': False, 'allow_put': False,
|
|
'is_visible': True},
|
|
'operating_status': {'allow_post': False, 'allow_put': False,
|
|
'is_visible': True},
|
|
'flavor_id': {'allow_post': True, 'allow_put': False,
|
|
'is_visible': True,
|
|
'validate': {'type:string': attr.NAME_MAX_LEN},
|
|
'default': attr.ATTR_NOT_SPECIFIED}
|
|
},
|
|
'listeners': {
|
|
'id': {'allow_post': False, 'allow_put': False,
|
|
'validate': {'type:uuid': None},
|
|
'is_visible': True,
|
|
'primary_key': True},
|
|
'tenant_id': {'allow_post': True, 'allow_put': False,
|
|
'validate': {'type:not_empty_string':
|
|
attr.TENANT_ID_MAX_LEN},
|
|
'required_by_policy': True,
|
|
'is_visible': True},
|
|
'name': {'allow_post': True, 'allow_put': True,
|
|
'validate': {'type:string': attr.NAME_MAX_LEN},
|
|
'default': '',
|
|
'is_visible': True},
|
|
'description': {'allow_post': True, 'allow_put': True,
|
|
'validate': {'type:string': attr.DESCRIPTION_MAX_LEN},
|
|
'is_visible': True, 'default': ''},
|
|
'loadbalancer_id': {'allow_post': True, 'allow_put': False,
|
|
'validate': {'type:uuid': None},
|
|
'is_visible': False},
|
|
'loadbalancers': {'allow_post': False, 'allow_put': False,
|
|
'is_visible': True},
|
|
'default_pool_id': {'allow_post': False, 'allow_put': False,
|
|
'validate': {'type:uuid': None},
|
|
'is_visible': True},
|
|
'default_tls_container_ref': {'allow_post': True,
|
|
'allow_put': True,
|
|
'default': None,
|
|
'validate': {'type:string_or_none': 128},
|
|
'is_visible': True},
|
|
'sni_container_refs': {'allow_post': True, 'allow_put': True,
|
|
'default': None,
|
|
'convert_to': attr.convert_to_list,
|
|
'is_visible': True},
|
|
'connection_limit': {'allow_post': True, 'allow_put': True,
|
|
'validate': {'type:connection_limit':
|
|
lb_const.MIN_CONNECT_VALUE},
|
|
'default': lb_const.MIN_CONNECT_VALUE,
|
|
'convert_to': attr.convert_to_int,
|
|
'is_visible': True},
|
|
'protocol': {'allow_post': True, 'allow_put': False,
|
|
'validate': {'type:values':
|
|
lb_const.LISTENER_SUPPORTED_PROTOCOLS},
|
|
'is_visible': True},
|
|
'protocol_port': {'allow_post': True, 'allow_put': False,
|
|
'validate': {'type:range': [0, 65535]},
|
|
'convert_to': attr.convert_to_int,
|
|
'is_visible': True},
|
|
'admin_state_up': {'allow_post': True, 'allow_put': True,
|
|
'default': True,
|
|
'convert_to': attr.convert_to_boolean,
|
|
'is_visible': True}
|
|
},
|
|
'pools': {
|
|
'id': {'allow_post': False, 'allow_put': False,
|
|
'validate': {'type:uuid': None},
|
|
'is_visible': True,
|
|
'primary_key': True},
|
|
'tenant_id': {'allow_post': True, 'allow_put': False,
|
|
'validate': {'type:not_empty_string':
|
|
attr.TENANT_ID_MAX_LEN},
|
|
'required_by_policy': True,
|
|
'is_visible': True},
|
|
'name': {'allow_post': True, 'allow_put': True,
|
|
'validate': {'type:string': attr.NAME_MAX_LEN},
|
|
'is_visible': True, 'default': ''},
|
|
'description': {'allow_post': True, 'allow_put': True,
|
|
'validate': {'type:string': attr.DESCRIPTION_MAX_LEN},
|
|
'is_visible': True, 'default': ''},
|
|
'listener_id': {'allow_post': True, 'allow_put': False,
|
|
'validate': {'type:uuid': None},
|
|
'is_visible': False},
|
|
'listeners': {'allow_post': False, 'allow_put': False,
|
|
'is_visible': True},
|
|
'healthmonitor_id': {'allow_post': False, 'allow_put': False,
|
|
'validate': {'type:uuid': None},
|
|
'is_visible': True},
|
|
'protocol': {'allow_post': True, 'allow_put': False,
|
|
'validate': {'type:values':
|
|
lb_const.POOL_SUPPORTED_PROTOCOLS},
|
|
'is_visible': True},
|
|
'lb_algorithm': {'allow_post': True, 'allow_put': True,
|
|
'validate': {
|
|
'type:values': lb_const.SUPPORTED_LB_ALGORITHMS},
|
|
'is_visible': True},
|
|
'session_persistence': {
|
|
'allow_post': True, 'allow_put': True,
|
|
'convert_to': attr.convert_none_to_empty_dict,
|
|
'default': {},
|
|
'validate': {
|
|
'type:dict_or_empty': {
|
|
'type': {
|
|
'type:values': lb_const.SUPPORTED_SP_TYPES,
|
|
'required': True},
|
|
'cookie_name': {'type:string': None,
|
|
'required': False}}},
|
|
'is_visible': True},
|
|
'members': {'allow_post': False, 'allow_put': False,
|
|
'is_visible': True},
|
|
'admin_state_up': {'allow_post': True, 'allow_put': True,
|
|
'default': True,
|
|
'convert_to': attr.convert_to_boolean,
|
|
'is_visible': True}
|
|
},
|
|
'healthmonitors': {
|
|
'id': {'allow_post': False, 'allow_put': False,
|
|
'validate': {'type:uuid': None},
|
|
'is_visible': True,
|
|
'primary_key': True},
|
|
'tenant_id': {'allow_post': True, 'allow_put': False,
|
|
'validate': {'type:not_empty_string':
|
|
attr.TENANT_ID_MAX_LEN},
|
|
'required_by_policy': True,
|
|
'is_visible': True},
|
|
'pool_id': {'allow_post': True, 'allow_put': False,
|
|
'validate': {'type:uuid': None},
|
|
'is_visible': False},
|
|
'pools': {'allow_post': False, 'allow_put': False,
|
|
'is_visible': True},
|
|
'type': {'allow_post': True, 'allow_put': False,
|
|
'validate': {
|
|
'type:values': lb_const.SUPPORTED_HEALTH_MONITOR_TYPES},
|
|
'is_visible': True},
|
|
'delay': {'allow_post': True, 'allow_put': True,
|
|
'validate': {'type:non_negative': None},
|
|
'convert_to': attr.convert_to_int,
|
|
'is_visible': True},
|
|
'timeout': {'allow_post': True, 'allow_put': True,
|
|
'validate': {'type:non_negative': None},
|
|
'convert_to': attr.convert_to_int,
|
|
'is_visible': True},
|
|
'max_retries': {'allow_post': True, 'allow_put': True,
|
|
'validate': {'type:range': [1, 10]},
|
|
'convert_to': attr.convert_to_int,
|
|
'is_visible': True},
|
|
'http_method': {'allow_post': True, 'allow_put': True,
|
|
'validate': {'type:values':
|
|
lb_const.SUPPORTED_HTTP_METHODS},
|
|
'default': 'GET',
|
|
'is_visible': True},
|
|
'url_path': {'allow_post': True, 'allow_put': True,
|
|
'validate': {'type:regex_or_none':
|
|
lb_const.SUPPORTED_URL_PATH},
|
|
'default': '/',
|
|
'is_visible': True},
|
|
'expected_codes': {
|
|
'allow_post': True,
|
|
'allow_put': True,
|
|
'validate': {
|
|
'type:regex': r'^(\d{3}(\s*,\s*\d{3})*)$|^(\d{3}-\d{3})$'
|
|
},
|
|
'default': '200',
|
|
'is_visible': True
|
|
},
|
|
'admin_state_up': {'allow_post': True, 'allow_put': True,
|
|
'default': True,
|
|
'convert_to': attr.convert_to_boolean,
|
|
'is_visible': True},
|
|
'name': {'allow_post': True, 'allow_put': True,
|
|
'validate': {'type:string': attr.NAME_MAX_LEN},
|
|
'default': '',
|
|
'is_visible': True}
|
|
}
|
|
}
|
|
|
|
SUB_RESOURCE_ATTRIBUTE_MAP = {
|
|
'members': {
|
|
'parent': {'collection_name': 'pools',
|
|
'member_name': 'pool'},
|
|
'parameters': {
|
|
'id': {'allow_post': False, 'allow_put': False,
|
|
'validate': {'type:uuid': None},
|
|
'is_visible': True,
|
|
'primary_key': True},
|
|
'tenant_id': {'allow_post': True, 'allow_put': False,
|
|
'validate': {'type:not_empty_string':
|
|
attr.TENANT_ID_MAX_LEN},
|
|
'required_by_policy': True,
|
|
'is_visible': True},
|
|
'address': {'allow_post': True, 'allow_put': False,
|
|
'validate': {'type:ip_address': None},
|
|
'is_visible': True},
|
|
'protocol_port': {'allow_post': True, 'allow_put': False,
|
|
'validate': {'type:range': [0, 65535]},
|
|
'convert_to': attr.convert_to_int,
|
|
'is_visible': True},
|
|
'weight': {'allow_post': True, 'allow_put': True,
|
|
'default': 1,
|
|
'validate': {'type:range': [0, 256]},
|
|
'convert_to': attr.convert_to_int,
|
|
'is_visible': True},
|
|
'admin_state_up': {'allow_post': True, 'allow_put': True,
|
|
'default': True,
|
|
'convert_to': attr.convert_to_boolean,
|
|
'is_visible': True},
|
|
'subnet_id': {'allow_post': True, 'allow_put': False,
|
|
'validate': {'type:uuid': None},
|
|
'is_visible': True},
|
|
'name': {'allow_post': True, 'allow_put': True,
|
|
'validate': {'type:string': attr.NAME_MAX_LEN},
|
|
'default': '',
|
|
'is_visible': True},
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
lbaasv2_quota_opts = [
|
|
cfg.IntOpt('quota_loadbalancer',
|
|
default=10,
|
|
help=_('Number of LoadBalancers allowed per tenant. '
|
|
'A negative value means unlimited.')),
|
|
cfg.IntOpt('quota_listener',
|
|
default=-1,
|
|
help=_('Number of Loadbalancer Listeners allowed per tenant. '
|
|
'A negative value means unlimited.')),
|
|
cfg.IntOpt('quota_pool',
|
|
default=10,
|
|
help=_('Number of pools allowed per tenant. '
|
|
'A negative value means unlimited.')),
|
|
cfg.IntOpt('quota_member',
|
|
default=-1,
|
|
help=_('Number of pool members allowed per tenant. '
|
|
'A negative value means unlimited.')),
|
|
cfg.IntOpt('quota_healthmonitor',
|
|
default=-1,
|
|
help=_('Number of health monitors allowed per tenant. '
|
|
'A negative value means unlimited.'))
|
|
]
|
|
cfg.CONF.register_opts(lbaasv2_quota_opts, 'QUOTAS')
|
|
|
|
|
|
class Loadbalancerv2(extensions.ExtensionDescriptor):
|
|
|
|
@classmethod
|
|
def get_name(cls):
|
|
return "LoadBalancing service v2"
|
|
|
|
@classmethod
|
|
def get_alias(cls):
|
|
return "lbaasv2"
|
|
|
|
@classmethod
|
|
def get_description(cls):
|
|
return "Extension for LoadBalancing service v2"
|
|
|
|
@classmethod
|
|
def get_namespace(cls):
|
|
return "http://wiki.openstack.org/neutron/LBaaS/API_2.0"
|
|
|
|
@classmethod
|
|
def get_updated(cls):
|
|
return "2014-06-18T10:00:00-00:00"
|
|
|
|
@classmethod
|
|
def get_resources(cls):
|
|
plural_mappings = resource_helper.build_plural_mappings(
|
|
{}, RESOURCE_ATTRIBUTE_MAP)
|
|
action_map = {'loadbalancer': {'stats': 'GET', 'statuses': 'GET'}}
|
|
plural_mappings['members'] = 'member'
|
|
plural_mappings['sni_container_refs'] = 'sni_container_ref'
|
|
attr.PLURALS.update(plural_mappings)
|
|
resources = resource_helper.build_resource_info(
|
|
plural_mappings,
|
|
RESOURCE_ATTRIBUTE_MAP,
|
|
constants.LOADBALANCERV2,
|
|
action_map=action_map,
|
|
register_quota=True)
|
|
plugin = manager.NeutronManager.get_service_plugins()[
|
|
constants.LOADBALANCERV2]
|
|
for collection_name in SUB_RESOURCE_ATTRIBUTE_MAP:
|
|
# Special handling needed for sub-resources with 'y' ending
|
|
# (e.g. proxies -> proxy)
|
|
resource_name = collection_name[:-1]
|
|
parent = SUB_RESOURCE_ATTRIBUTE_MAP[collection_name].get('parent')
|
|
params = SUB_RESOURCE_ATTRIBUTE_MAP[collection_name].get(
|
|
'parameters')
|
|
|
|
controller = base.create_resource(collection_name, resource_name,
|
|
plugin, params,
|
|
allow_bulk=True,
|
|
parent=parent,
|
|
allow_pagination=True,
|
|
allow_sorting=True)
|
|
|
|
resource = extensions.ResourceExtension(
|
|
collection_name,
|
|
controller, parent,
|
|
path_prefix=LOADBALANCERV2_PREFIX,
|
|
attr_map=params)
|
|
resources.append(resource)
|
|
|
|
return resources
|
|
|
|
@classmethod
|
|
def get_plugin_interface(cls):
|
|
return LoadBalancerPluginBaseV2
|
|
|
|
def update_attributes_map(self, attributes, extension_attrs_map=None):
|
|
super(Loadbalancerv2, self).update_attributes_map(
|
|
attributes, extension_attrs_map=RESOURCE_ATTRIBUTE_MAP)
|
|
|
|
def get_extended_resources(self, version):
|
|
if version == "2.0":
|
|
return RESOURCE_ATTRIBUTE_MAP
|
|
else:
|
|
return {}
|
|
|
|
|
|
@six.add_metaclass(abc.ABCMeta)
|
|
class LoadBalancerPluginBaseV2(service_base.ServicePluginBase):
|
|
|
|
def get_plugin_name(self):
|
|
return constants.LOADBALANCERV2
|
|
|
|
def get_plugin_type(self):
|
|
return constants.LOADBALANCERV2
|
|
|
|
def get_plugin_description(self):
|
|
return 'LoadBalancer service plugin v2'
|
|
|
|
@abc.abstractmethod
|
|
def get_loadbalancers(self, context, filters=None, fields=None):
|
|
pass
|
|
|
|
@abc.abstractmethod
|
|
def get_loadbalancer(self, context, id, fields=None):
|
|
pass
|
|
|
|
@abc.abstractmethod
|
|
def create_loadbalancer(self, context, loadbalancer):
|
|
pass
|
|
|
|
@abc.abstractmethod
|
|
def update_loadbalancer(self, context, id, loadbalancer):
|
|
pass
|
|
|
|
@abc.abstractmethod
|
|
def delete_loadbalancer(self, context, id):
|
|
pass
|
|
|
|
@abc.abstractmethod
|
|
def create_listener(self, context, listener):
|
|
pass
|
|
|
|
@abc.abstractmethod
|
|
def get_listener(self, context, id, fields=None):
|
|
pass
|
|
|
|
@abc.abstractmethod
|
|
def get_listeners(self, context, filters=None, fields=None):
|
|
pass
|
|
|
|
@abc.abstractmethod
|
|
def update_listener(self, context, id, listener):
|
|
pass
|
|
|
|
@abc.abstractmethod
|
|
def delete_listener(self, context, id):
|
|
pass
|
|
|
|
@abc.abstractmethod
|
|
def get_pools(self, context, filters=None, fields=None):
|
|
pass
|
|
|
|
@abc.abstractmethod
|
|
def get_pool(self, context, id, fields=None):
|
|
pass
|
|
|
|
@abc.abstractmethod
|
|
def create_pool(self, context, pool):
|
|
pass
|
|
|
|
@abc.abstractmethod
|
|
def update_pool(self, context, id, pool):
|
|
pass
|
|
|
|
@abc.abstractmethod
|
|
def delete_pool(self, context, id):
|
|
pass
|
|
|
|
@abc.abstractmethod
|
|
def stats(self, context, loadbalancer_id):
|
|
pass
|
|
|
|
@abc.abstractmethod
|
|
def get_pool_members(self, context, pool_id,
|
|
filters=None,
|
|
fields=None):
|
|
pass
|
|
|
|
@abc.abstractmethod
|
|
def get_pool_member(self, context, id, pool_id,
|
|
fields=None):
|
|
pass
|
|
|
|
@abc.abstractmethod
|
|
def create_pool_member(self, context, pool_id, member):
|
|
pass
|
|
|
|
@abc.abstractmethod
|
|
def update_pool_member(self, context, id, pool_id, member):
|
|
pass
|
|
|
|
@abc.abstractmethod
|
|
def delete_pool_member(self, context, id, pool_id):
|
|
pass
|
|
|
|
@abc.abstractmethod
|
|
def get_healthmonitors(self, context, filters=None, fields=None):
|
|
pass
|
|
|
|
@abc.abstractmethod
|
|
def get_healthmonitor(self, context, id, fields=None):
|
|
pass
|
|
|
|
@abc.abstractmethod
|
|
def create_healthmonitor(self, context, healthmonitor):
|
|
pass
|
|
|
|
@abc.abstractmethod
|
|
def update_healthmonitor(self, context, id, healthmonitor):
|
|
pass
|
|
|
|
@abc.abstractmethod
|
|
def delete_healthmonitor(self, context, id):
|
|
pass
|
|
|
|
@abc.abstractmethod
|
|
def get_members(self, context, filters=None, fields=None):
|
|
pass
|
|
|
|
@abc.abstractmethod
|
|
def get_member(self, context, id, fields=None):
|
|
pass
|
|
|
|
@abc.abstractmethod
|
|
def statuses(self, context, loadbalancer_id):
|
|
pass
|