Get Me A Load Balancer API

Change-Id: Id3a5ddb8efded8c6ad72a7118424ec01c777318d
This commit is contained in:
Brandon Logan 2015-12-08 11:13:26 -06:00
parent 06f46b7cec
commit 37186b62d1
14 changed files with 511 additions and 69 deletions

View File

@ -16,9 +16,6 @@ from oslo_config import cfg
from pecan import rest
from stevedore import driver as stevedore_driver
from octavia.api.v1.types import listener as listener_types
from octavia.api.v1.types import load_balancer as lb_types
from octavia.api.v1.types import pool as pool_types
from octavia.db import repositories
CONF = cfg.CONF
@ -35,7 +32,7 @@ class BaseController(rest.RestController):
).driver
@staticmethod
def _convert_db_to_type(db_entity, to_type):
def _convert_db_to_type(db_entity, to_type, children=False):
"""Converts a data model into a Octavia WSME type
:param db_entity: data model to convert
@ -45,18 +42,7 @@ class BaseController(rest.RestController):
to_type = to_type[0]
def _convert(db_obj):
api_type = to_type.from_data_model(db_obj)
if to_type == lb_types.LoadBalancerResponse:
api_type.vip = lb_types.VIP.from_data_model(db_obj.vip)
elif (to_type == pool_types.PoolResponse
and db_obj.session_persistence):
api_type.session_persistence = (
pool_types.SessionPersistenceResponse.from_data_model(
db_obj.session_persistence))
elif to_type == listener_types.ListenerResponse:
api_type.sni_containers = [sni_c.tls_container_id
for sni_c in db_obj.sni_containers]
return api_type
return to_type.from_data_model(db_obj, children=children)
if isinstance(db_entity, list):
converted = [_convert(db_obj) for db_obj in db_entity]
else:

View File

@ -24,6 +24,7 @@ from octavia.api.v1.types import health_monitor as hm_types
from octavia.common import constants
from octavia.common import data_models
from octavia.common import exceptions
from octavia.db import prepare as db_prepare
from octavia.i18n import _LI
@ -66,8 +67,9 @@ class HealthMonitorController(base.BaseController):
raise exceptions.DuplicateHealthMonitor()
except exceptions.NotFound:
pass
hm_dict = health_monitor.to_dict()
hm_dict['pool_id'] = self.pool_id
hm_dict = db_prepare.create_health_monitor(
health_monitor.to_dict(), self.pool_id)
# Verify load balancer is in a mutable status. If so it can be assumed
# that the listener is also in a mutable status because a load balancer
# will only be ACTIVE when all it's listeners as ACTIVE.

View File

@ -27,6 +27,7 @@ from octavia.common import constants
from octavia.common import data_models
from octavia.common import exceptions
from octavia.db import api as db_api
from octavia.db import prepare as db_prepare
from octavia.i18n import _LI
@ -84,16 +85,15 @@ class ListenersController(base.BaseController):
Update the load balancer db when provisioning status changes.
"""
try:
sni_container_ids = listener_dict.pop('sni_containers')
sni_containers = listener_dict.pop('sni_containers', [])
db_listener = self.repositories.listener.create(
context.session, **listener_dict)
if sni_container_ids is not None:
for container_id in sni_container_ids:
sni_dict = {'listener_id': db_listener.id,
'tls_container_id': container_id}
self.repositories.sni.create(context.session, **sni_dict)
db_listener = self.repositories.listener.get(context.session,
id=db_listener.id)
if sni_containers:
for sni_container in sni_containers:
self.repositories.sni.create(
context.session, **sni_container)
db_listener = self.repositories.listener.get(
context.session, id=db_listener.id)
except odb_exceptions.DBDuplicateEntry as de:
# Setting LB back to active because this is just a validation
# failure
@ -133,14 +133,8 @@ class ListenersController(base.BaseController):
self._secure_data(listener)
lb_repo = self.repositories.load_balancer
self._test_lb_status_post(context, lb_repo)
listener_dict = listener.to_dict()
listener_dict['load_balancer_id'] = self.load_balancer_id
listener_dict['provisioning_status'] = constants.PENDING_CREATE
listener_dict['operating_status'] = constants.OFFLINE
# NOTE(blogan): Throwing away because we should not store secure data
# in the database nor should we send it to a handler.
if 'tls_termination' in listener_dict:
del listener_dict['tls_termination']
listener_dict = db_prepare.create_listener(
listener.to_dict(), self.load_balancer_id)
# This is the extra validation layer for wrong protocol or duplicate
# listeners on the same load balancer.
return self._validate_listeners(context, lb_repo, listener_dict)

View File

@ -26,6 +26,7 @@ from octavia.common import constants
from octavia.common import data_models
from octavia.common import exceptions
from octavia.db import api as db_api
from octavia.db import prepare as db_prepare
from octavia.i18n import _LI
@ -65,19 +66,38 @@ class LoadBalancersController(base.BaseController):
return self._convert_db_to_type(load_balancers,
[lb_types.LoadBalancerResponse])
def _create_load_balancer_tree(self, context, load_balancer):
prepped_lb = db_prepare.create_load_balancer_tree(
load_balancer.to_dict())
try:
db_lb = self.repositories.create_load_balancer_tree(
context.session, prepped_lb)
except Exception:
# TODO(blogan): handle exceptions
raise
try:
LOG.info(_LI("Sending full load balancer configuration %s to "
"the handler"), db_lb.id)
self.handler.create(db_lb)
except Exception:
with excutils.save_and_reraise_exception(reraise=False):
self.repositories.load_balancer.update(
context.session, db_lb.id,
provisioning_status=constants.ERROR)
return self._convert_db_to_type(db_lb, lb_types.LoadBalancerResponse,
children=True)
@wsme_pecan.wsexpose(lb_types.LoadBalancerResponse,
body=lb_types.LoadBalancerPOST, status_code=202)
def post(self, load_balancer):
"""Creates a load balancer."""
context = pecan.request.context.get('octavia_context')
lb_dict = load_balancer.to_dict()
vip_dict = lb_dict.pop('vip')
lb_dict['provisioning_status'] = constants.PENDING_CREATE
lb_dict['operating_status'] = constants.OFFLINE
lb_dict['project_id'] = lb_dict.get('project_id') or context.project_id
if load_balancer.listeners:
return self._create_load_balancer_tree(context, load_balancer)
lb_dict = db_prepare.create_load_balancer(load_balancer.to_dict())
try:
db_lb = self.repositories.create_load_balancer_and_vip(
context.session, lb_dict, vip_dict)
context.session, lb_dict, lb_dict.pop('vip', {}))
except odb_exceptions.DBDuplicateEntry:
raise exceptions.IDAlreadyExists()
# Handler will be responsible for sending to controller

View File

@ -25,6 +25,7 @@ from octavia.api.v1.types import member as member_types
from octavia.common import constants
from octavia.common import data_models
from octavia.common import exceptions
from octavia.db import prepare as db_prepare
from octavia.i18n import _LI
@ -65,9 +66,8 @@ class MembersController(base.BaseController):
def post(self, member):
"""Creates a pool member on a pool."""
context = pecan.request.context.get('octavia_context')
member_dict = member.to_dict()
member_dict['pool_id'] = self.pool_id
member_dict['operating_status'] = constants.OFFLINE
member_dict = db_prepare.create_member(member.to_dict(), self.pool_id)
# Verify load balancer is in a mutable status. If so it can be assumed
# that the listener is also in a mutable status because a load balancer
# will only be ACTIVE when all its listeners as ACTIVE.

View File

@ -27,6 +27,7 @@ from octavia.api.v1.types import pool as pool_types
from octavia.common import constants
from octavia.common import data_models
from octavia.common import exceptions
from octavia.db import prepare as db_prepare
from octavia.i18n import _LI
@ -131,9 +132,8 @@ class PoolsController(base.BaseController):
# will only be ACTIVE when all it's listeners as ACTIVE.
self._test_lb_status(context.session)
pool_dict = pool.to_dict()
pool_dict = db_prepare.create_pool(pool.to_dict())
sp_dict = pool_dict.pop('session_persistence', None)
pool_dict['operating_status'] = constants.OFFLINE
return self._validate_create_pool(context.session, sp_dict, pool_dict)

View File

@ -40,10 +40,11 @@ class IPAddressType(wtypes.UserType):
class BaseType(wtypes.Base):
@classmethod
def from_data_model(cls, data_model):
def from_data_model(cls, data_model, children=False):
"""Converts data_model to Octavia WSME type.
:param data_model: data model to convert from
:param children: convert child data models
"""
return cls(**data_model.to_dict())
@ -62,6 +63,9 @@ class BaseType(wtypes.Base):
continue
if value and isinstance(value, BaseType):
value = value.to_dict()
if value and isinstance(value, list):
value = [val.to_dict() if isinstance(val, BaseType) else val
for val in value]
if isinstance(value, wtypes.UnsetType):
if render_unsets:
value = None

View File

@ -15,6 +15,7 @@
from wsme import types as wtypes
from octavia.api.v1.types import base
from octavia.api.v1.types import pool
class TLSTermination(base.BaseType):
@ -38,6 +39,27 @@ class ListenerResponse(base.BaseType):
tls_certificate_id = wtypes.wsattr(wtypes.StringType(max_length=255))
sni_containers = [wtypes.StringType(max_length=255)]
project_id = wtypes.wsattr(wtypes.UuidType())
default_pool = wtypes.wsattr(pool.PoolResponse)
@classmethod
def from_data_model(cls, data_model, children=False):
listener = super(ListenerResponse, cls).from_data_model(
data_model, children=children)
# NOTE(blogan): we should show sni_containers for every call to show
# a listener
listener.sni_containers = [sni_c.tls_container_id
for sni_c in data_model.sni_containers]
if not children:
# NOTE(blogan): do not show default_pool if the request does not
# want to see children
del listener.default_pool
return listener
if data_model.default_pool:
listener.default_pool = pool.PoolResponse.from_data_model(
data_model.default_pool, children=children)
if not listener.default_pool:
del listener.default_pool
return listener
class ListenerPOST(base.BaseType):
@ -53,6 +75,7 @@ class ListenerPOST(base.BaseType):
tls_termination = wtypes.wsattr(TLSTermination)
sni_containers = [wtypes.StringType(max_length=255)]
project_id = wtypes.wsattr(wtypes.UuidType())
default_pool = wtypes.wsattr(pool.PoolPOST)
class ListenerPUT(base.BaseType):

View File

@ -15,6 +15,7 @@
from wsme import types as wtypes
from octavia.api.v1.types import base
from octavia.api.v1.types import listener
class VIP(base.BaseType):
@ -34,6 +35,26 @@ class LoadBalancerResponse(base.BaseType):
enabled = wtypes.wsattr(bool)
vip = wtypes.wsattr(VIP)
project_id = wtypes.wsattr(wtypes.UuidType())
listeners = wtypes.wsattr([listener.ListenerResponse])
@classmethod
def from_data_model(cls, data_model, children=False):
lb = super(LoadBalancerResponse, cls).from_data_model(
data_model, children=children)
# NOTE(blogan): VIP is technically a child but its the main piece of
# a load balancer so it makes sense to show it no matter what.
lb.vip = VIP.from_data_model(data_model.vip)
if not children:
# NOTE(blogan): don't show listeners if the request does not want
# to see children
del lb.listeners
return lb
lb.listeners = [
listener.ListenerResponse.from_data_model(
listener_dm, children=children)
for listener_dm in data_model.listeners
]
return lb
class LoadBalancerPOST(base.BaseType):
@ -44,6 +65,7 @@ class LoadBalancerPOST(base.BaseType):
enabled = wtypes.wsattr(bool, default=True)
vip = wtypes.wsattr(VIP, mandatory=True)
project_id = wtypes.wsattr(wtypes.UuidType())
listeners = wtypes.wsattr([listener.ListenerPOST], default=[])
class LoadBalancerPUT(base.BaseType):

View File

@ -15,6 +15,8 @@
from wsme import types as wtypes
from octavia.api.v1.types import base
from octavia.api.v1.types import health_monitor
from octavia.api.v1.types import member
class SessionPersistenceResponse(base.BaseType):
@ -46,6 +48,36 @@ class PoolResponse(base.BaseType):
lb_algorithm = wtypes.wsattr(wtypes.text)
session_persistence = wtypes.wsattr(SessionPersistenceResponse)
project_id = wtypes.wsattr(wtypes.UuidType())
health_monitor = wtypes.wsattr(health_monitor.HealthMonitorResponse)
members = wtypes.wsattr([member.MemberResponse])
@classmethod
def from_data_model(cls, data_model, children=False):
pool = super(PoolResponse, cls).from_data_model(
data_model, children=children)
# NOTE(blogan): we should show session persistence on every request
# to show a pool
if data_model.session_persistence:
pool.session_persistence = (
SessionPersistenceResponse.from_data_model(
data_model.session_persistence))
if not children:
# NOTE(blogan): do not show members or health_monitor if the
# request does not want to see children
del pool.members
del pool.health_monitor
return pool
pool.members = [
member.MemberResponse.from_data_model(member_dm, children=children)
for member_dm in data_model.members
]
if data_model.health_monitor:
pool.health_monitor = (
health_monitor.HealthMonitorResponse.from_data_model(
data_model.health_monitor, children=children))
if not pool.health_monitor:
del pool.health_monitor
return pool
class PoolPOST(base.BaseType):
@ -58,6 +90,8 @@ class PoolPOST(base.BaseType):
lb_algorithm = wtypes.wsattr(wtypes.text, mandatory=True)
session_persistence = wtypes.wsattr(SessionPersistencePOST)
project_id = wtypes.wsattr(wtypes.UuidType())
health_monitor = wtypes.wsattr(health_monitor.HealthMonitorPOST)
members = wtypes.wsattr([member.MemberPOST])
class PoolPUT(base.BaseType):

91
octavia/db/prepare.py Normal file
View File

@ -0,0 +1,91 @@
# Copyright 2015 Rackspace
#
# 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.
from oslo_utils import uuidutils
from octavia.common import constants
def create_load_balancer_tree(lb_dict):
listeners = lb_dict.pop('listeners', [])
prepped_lb = create_load_balancer(lb_dict)
prepped_lb['listeners'] = []
for listener_dict in listeners:
pool = listener_dict.pop('default_pool', None)
prepped_listener = create_listener(listener_dict, prepped_lb.get('id'))
if pool:
hm = pool.pop('health_monitor', None)
members = pool.pop('members', []) or []
prepped_pool = create_pool(pool)
pool_id = prepped_pool.get('id')
if hm:
prepped_hm = create_health_monitor(hm, pool_id)
prepped_pool['health_monitor'] = prepped_hm
prepped_pool['members'] = []
for member_dict in members:
prepped_pool['members'].append(
create_member(member_dict, pool_id))
prepped_listener['default_pool'] = prepped_pool
prepped_lb['listeners'].append(prepped_listener)
return prepped_lb
def create_load_balancer(lb_dict):
if not lb_dict.get('id'):
lb_dict['id'] = uuidutils.generate_uuid()
if lb_dict.get('vip'):
lb_dict['vip']['load_balancer_id'] = lb_dict.get('id')
lb_dict['provisioning_status'] = constants.PENDING_CREATE
lb_dict['operating_status'] = constants.OFFLINE
return lb_dict
def create_listener(listener_dict, lb_id):
if not listener_dict.get('id'):
listener_dict['id'] = uuidutils.generate_uuid()
listener_dict['load_balancer_id'] = lb_id
listener_dict['provisioning_status'] = constants.PENDING_CREATE
listener_dict['operating_status'] = constants.OFFLINE
# NOTE(blogan): Throwing away because we should not store secure data
# in the database nor should we send it to a handler.
if 'tls_termination' in listener_dict:
del listener_dict['tls_termination']
sni_container_ids = listener_dict.pop('sni_containers', []) or []
sni_containers = [{'listener_id': listener_dict.get('id'),
'tls_container_id': sni_container_id}
for sni_container_id in sni_container_ids]
listener_dict['sni_containers'] = sni_containers
return listener_dict
def create_pool(pool_dict):
if not pool_dict.get('id'):
pool_dict['id'] = uuidutils.generate_uuid()
if pool_dict.get('session_persistence'):
pool_dict['session_persistence']['pool_id'] = pool_dict.get('id')
if 'members' in pool_dict and not pool_dict.get('members'):
del pool_dict['members']
pool_dict['operating_status'] = constants.OFFLINE
return pool_dict
def create_member(member_dict, pool_id):
member_dict['pool_id'] = pool_id
member_dict['operating_status'] = constants.OFFLINE
return member_dict
def create_health_monitor(hm_dict, pool_id):
hm_dict['pool_id'] = pool_id
return hm_dict

View File

@ -21,7 +21,6 @@ import datetime
from oslo_config import cfg
from oslo_log import log as logging
from oslo_utils import uuidutils
from octavia.common import constants
from octavia.common import exceptions
@ -134,6 +133,37 @@ class Repositories(object):
self.amphorahealth = AmphoraHealthRepository()
self.vrrpgroup = VRRPGroupRepository()
def _create_lb_and_vip_transaction(self, session, lb_dict, vip_dict):
with session.begin(subtransactions=True):
lb = models.LoadBalancer(**lb_dict)
session.add(lb)
vip_dict['load_balancer_id'] = lb_dict['id']
vip = models.Vip(**vip_dict)
session.add(vip)
return lb
def create_load_balancer_tree(self, session, lb_dict):
listener_dicts = lb_dict.pop('listeners', [])
vip_dict = lb_dict.pop('vip')
with session.begin(subtransactions=True):
lb_dm = self._create_lb_and_vip_transaction(
session, lb_dict, vip_dict)
for listener_dict in listener_dicts:
pool_dict = listener_dict.pop('default_pool', None)
if pool_dict:
hm_dict = pool_dict.pop('health_monitor', None)
member_dicts = pool_dict.pop('members', [])
pool_dm = self.pool.create(session, **pool_dict)
if hm_dict:
hm_dict['pool_id'] = pool_dm.id
self.health_monitor.create(session, **hm_dict)
for member_dict in member_dicts:
member_dict['pool_id'] = pool_dm.id
self.member.create(session, **member_dict)
listener_dict['default_pool_id'] = pool_dm.id
self.listener.create(session, **listener_dict)
return self.load_balancer.get(session, id=lb_dm.id)
def create_load_balancer_and_vip(self, session, lb_dict, vip_dict):
"""Inserts load balancer and vip entities into the database.
@ -145,14 +175,9 @@ class Repositories(object):
:param vip_dict: Dictionary representation of a vip
:returns: octava.common.data_models.LoadBalancer
"""
with session.begin():
if not lb_dict.get('id'):
lb_dict['id'] = uuidutils.generate_uuid()
lb = models.LoadBalancer(**lb_dict)
session.add(lb)
vip_dict['load_balancer_id'] = lb_dict['id']
vip = models.Vip(**vip_dict)
session.add(vip)
with session.begin(subtransactions=True):
lb = self._create_lb_and_vip_transaction(
session, lb_dict, vip_dict)
return self.load_balancer.get(session, id=lb.id)
def create_pool_on_listener(self, session, listener_id,
@ -166,11 +191,8 @@ class Repositories(object):
:returns: octavia.common.data_models.Pool
"""
with session.begin(subtransactions=True):
if not pool_dict.get('id'):
pool_dict['id'] = uuidutils.generate_uuid()
db_pool = self.pool.create(session, **pool_dict)
if sp_dict:
sp_dict['pool_id'] = pool_dict['id']
self.session_persistence.create(session, **sp_dict)
self.listener.update(session, listener_id,
default_pool_id=pool_dict['id'])

View File

@ -11,6 +11,9 @@
# 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 copy
from oslo_utils import uuidutils
from octavia.common import constants
@ -225,3 +228,233 @@ class TestLoadBalancer(base.BaseAPITest):
def test_delete_bad_lb_id(self):
path = self.LB_PATH.format(lb_id='bad_uuid')
self.delete(path, status=404)
class TestLoadBalancerGraph(base.BaseAPITest):
def setUp(self):
super(TestLoadBalancerGraph, self).setUp()
self._project_id = uuidutils.generate_uuid()
def _assert_graphs_equal(self, expected_graph, observed_graph):
observed_graph_copy = copy.deepcopy(observed_graph)
obs_lb_id = observed_graph_copy.pop('id')
self.assertTrue(uuidutils.is_uuid_like(obs_lb_id))
expected_listeners = expected_graph.pop('listeners', [])
observed_listeners = observed_graph_copy.pop('listeners', [])
self.assertEqual(expected_graph, observed_graph_copy)
for observed_listener in observed_listeners:
self.assertTrue(uuidutils.is_uuid_like(
observed_listener.pop('id')))
default_pool = observed_listener.get('default_pool')
if default_pool:
self.assertTrue(default_pool.get('id'))
default_pool.pop('id')
hm = default_pool.get('healthmonitor')
if hm:
self.assertTrue(hm.get('id'))
hm.pop('id')
for member in default_pool.get('members', []):
self.assertTrue(member.get('id'))
member.pop('id')
self.assertIn(observed_listener, expected_listeners)
def _get_lb_bodies(self, create_listeners, expected_listeners):
create_lb = {
'name': 'lb1',
'project_id': self._project_id,
'vip': {},
'listeners': create_listeners
}
expected_lb = {
'description': None,
'enabled': True,
'provisioning_status': constants.PENDING_CREATE,
'operating_status': constants.OFFLINE
}
expected_lb.update(create_lb)
expected_lb['listeners'] = expected_listeners
expected_lb['vip'] = {'ip_address': None, 'port_id': None,
'subnet_id': None}
return create_lb, expected_lb
def _get_listener_bodies(self, name='listener1', protocol_port=80,
create_default_pool=None,
expected_default_pool=None):
create_listener = {
'name': name,
'protocol_port': protocol_port,
'protocol': constants.PROTOCOL_HTTP,
'project_id': self._project_id
}
if create_default_pool:
create_listener['default_pool'] = create_default_pool
expected_listener = {
'description': None,
'tls_certificate_id': None,
'sni_containers': [],
'connection_limit': None,
'enabled': True,
'provisioning_status': constants.PENDING_CREATE,
'operating_status': constants.OFFLINE
}
expected_listener.update(create_listener)
if expected_default_pool:
expected_listener['default_pool'] = expected_default_pool
return create_listener, expected_listener
def _get_pool_bodies(self, name='pool1', create_members=None,
expected_members=None, create_hm=None,
expected_hm=None):
create_pool = {
'name': name,
'protocol': constants.PROTOCOL_HTTP,
'lb_algorithm': constants.LB_ALGORITHM_ROUND_ROBIN,
'project_id': self._project_id
}
if create_members:
create_pool['members'] = create_members
if create_hm:
create_pool['health_monitor'] = create_hm
expected_pool = {
'description': None,
'session_persistence': None,
'members': [],
'enabled': True,
'operating_status': constants.OFFLINE
}
expected_pool.update(create_pool)
if expected_members:
expected_pool['members'] = expected_members
if expected_hm:
expected_pool['health_monitor'] = expected_hm
return create_pool, expected_pool
def _get_member_bodies(self):
create_member = {
'ip_address': '10.0.0.1',
'protocol_port': 80,
'project_id': self._project_id
}
expected_member = {
'weight': 1,
'enabled': True,
'subnet_id': None,
'operating_status': constants.OFFLINE
}
expected_member.update(create_member)
return create_member, expected_member
def _get_hm_bodies(self):
create_hm = {
'type': constants.HEALTH_MONITOR_PING,
'delay': 1,
'timeout': 1,
'fall_threshold': 1,
'rise_threshold': 1,
'project_id': self._project_id
}
expected_hm = {
'http_method': None,
'url_path': None,
'expected_codes': None,
'enabled': True
}
expected_hm.update(create_hm)
return create_hm, expected_hm
def test_with_one_listener(self):
create_listener, expected_listener = self._get_listener_bodies()
create_lb, expected_lb = self._get_lb_bodies([create_listener],
[expected_listener])
response = self.post(self.LBS_PATH, create_lb)
api_lb = response.json
self._assert_graphs_equal(expected_lb, api_lb)
def test_with_many_listeners(self):
create_listener1, expected_listener1 = self._get_listener_bodies()
create_listener2, expected_listener2 = self._get_listener_bodies(
name='listener2', protocol_port=81
)
create_lb, expected_lb = self._get_lb_bodies(
[create_listener1, create_listener2],
[expected_listener1, expected_listener2])
response = self.post(self.LBS_PATH, create_lb)
api_lb = response.json
self._assert_graphs_equal(expected_lb, api_lb)
def test_with_one_listener_one_pool(self):
create_pool, expected_pool = self._get_pool_bodies()
create_listener, expected_listener = self._get_listener_bodies(
create_default_pool=create_pool,
expected_default_pool=expected_pool
)
create_lb, expected_lb = self._get_lb_bodies([create_listener],
[expected_listener])
response = self.post(self.LBS_PATH, create_lb)
api_lb = response.json
self._assert_graphs_equal(expected_lb, api_lb)
def test_with_many_listeners_one_pool(self):
create_pool1, expected_pool1 = self._get_pool_bodies()
create_pool2, expected_pool2 = self._get_pool_bodies(name='pool2')
create_listener1, expected_listener1 = self._get_listener_bodies(
create_default_pool=create_pool1,
expected_default_pool=expected_pool1
)
create_listener2, expected_listener2 = self._get_listener_bodies(
create_default_pool=create_pool2,
expected_default_pool=expected_pool2,
name='listener2', protocol_port=81
)
create_lb, expected_lb = self._get_lb_bodies(
[create_listener1, create_listener2],
[expected_listener1, expected_listener2])
response = self.post(self.LBS_PATH, create_lb)
api_lb = response.json
self._assert_graphs_equal(expected_lb, api_lb)
def test_with_one_listener_one_member(self):
create_member, expected_member = self._get_member_bodies()
create_pool, expected_pool = self._get_pool_bodies(
create_members=[create_member],
expected_members=[expected_member])
create_listener, expected_listener = self._get_listener_bodies(
create_default_pool=create_pool,
expected_default_pool=expected_pool)
create_lb, expected_lb = self._get_lb_bodies([create_listener],
[expected_listener])
response = self.post(self.LBS_PATH, create_lb)
api_lb = response.json
self._assert_graphs_equal(expected_lb, api_lb)
def test_with_one_listener_one_hm(self):
create_hm, expected_hm = self._get_hm_bodies()
create_pool, expected_pool = self._get_pool_bodies(
create_hm=create_hm,
expected_hm=expected_hm)
create_listener, expected_listener = self._get_listener_bodies(
create_default_pool=create_pool,
expected_default_pool=expected_pool)
create_lb, expected_lb = self._get_lb_bodies([create_listener],
[expected_listener])
response = self.post(self.LBS_PATH, create_lb)
api_lb = response.json
self._assert_graphs_equal(expected_lb, api_lb)
def test_with_one_of_everything(self):
create_member, expected_member = self._get_member_bodies()
create_hm, expected_hm = self._get_hm_bodies()
create_pool, expected_pool = self._get_pool_bodies(
create_members=[create_member],
expected_members=[expected_member],
create_hm=create_hm,
expected_hm=expected_hm)
create_listener, expected_listener = self._get_listener_bodies(
create_default_pool=create_pool,
expected_default_pool=expected_pool)
create_lb, expected_lb = self._get_lb_bodies([create_listener],
[expected_listener])
response = self.post(self.LBS_PATH, create_lb)
api_lb = response.json
self._assert_graphs_equal(expected_lb, api_lb)

View File

@ -109,7 +109,8 @@ class AllRepositoriesTest(base.OctaviaDBTestBase):
'operating_status': constants.OFFLINE,
'topology': constants.TOPOLOGY_ACTIVE_STANDBY,
'vrrp_group': None,
'project_id': uuidutils.generate_uuid()}
'project_id': uuidutils.generate_uuid(),
'id': uuidutils.generate_uuid()}
vip = {'ip_address': '10.0.0.1',
'port_id': uuidutils.generate_uuid(),
'subnet_id': uuidutils.generate_uuid()}
@ -129,7 +130,8 @@ class AllRepositoriesTest(base.OctaviaDBTestBase):
'description': 'desc1',
'lb_algorithm': constants.LB_ALGORITHM_ROUND_ROBIN,
'enabled': True, 'operating_status': constants.ONLINE,
'project_id': uuidutils.generate_uuid()}
'project_id': uuidutils.generate_uuid(),
'id': uuidutils.generate_uuid()}
pool_dm = self.repos.create_pool_on_listener(self.session,
self.listener.id,
pool)
@ -148,9 +150,11 @@ class AllRepositoriesTest(base.OctaviaDBTestBase):
'description': 'desc1',
'lb_algorithm': constants.LB_ALGORITHM_ROUND_ROBIN,
'enabled': True, 'operating_status': constants.ONLINE,
'project_id': uuidutils.generate_uuid()}
'project_id': uuidutils.generate_uuid(),
'id': uuidutils.generate_uuid()}
sp = {'type': constants.SESSION_PERSISTENCE_HTTP_COOKIE,
'cookie_name': 'cookie_monster'}
'cookie_name': 'cookie_monster',
'pool_id': pool['id']}
pool_dm = self.repos.create_pool_on_listener(self.session,
self.listener.id,
pool, sp_dict=sp)
@ -176,7 +180,8 @@ class AllRepositoriesTest(base.OctaviaDBTestBase):
'description': 'desc1',
'lb_algorithm': constants.LB_ALGORITHM_ROUND_ROBIN,
'enabled': True, 'operating_status': constants.ONLINE,
'project_id': uuidutils.generate_uuid()}
'project_id': uuidutils.generate_uuid(),
'id': uuidutils.generate_uuid()}
pool_dm = self.repos.create_pool_on_listener(self.session,
self.listener.id, pool)
update_pool = {'protocol': constants.PROTOCOL_TCP, 'name': 'up_pool'}
@ -196,9 +201,11 @@ class AllRepositoriesTest(base.OctaviaDBTestBase):
'description': 'desc1',
'lb_algorithm': constants.LB_ALGORITHM_ROUND_ROBIN,
'enabled': True, 'operating_status': constants.ONLINE,
'project_id': uuidutils.generate_uuid()}
'project_id': uuidutils.generate_uuid(),
'id': uuidutils.generate_uuid()}
sp = {'type': constants.SESSION_PERSISTENCE_HTTP_COOKIE,
'cookie_name': 'cookie_monster'}
'cookie_name': 'cookie_monster',
'pool_id': pool['id']}
pool_dm = self.repos.create_pool_on_listener(self.session,
self.listener.id,
pool, sp_dict=sp)
@ -224,7 +231,8 @@ class AllRepositoriesTest(base.OctaviaDBTestBase):
'description': 'desc1',
'lb_algorithm': constants.LB_ALGORITHM_ROUND_ROBIN,
'enabled': True, 'operating_status': constants.ONLINE,
'project_id': uuidutils.generate_uuid()}
'project_id': uuidutils.generate_uuid(),
'id': uuidutils.generate_uuid()}
pool_dm = self.repos.create_pool_on_listener(self.session,
self.listener.id,
pool)
@ -244,7 +252,8 @@ class AllRepositoriesTest(base.OctaviaDBTestBase):
'description': 'desc1',
'lb_algorithm': constants.LB_ALGORITHM_ROUND_ROBIN,
'enabled': True, 'operating_status': constants.ONLINE,
'project_id': uuidutils.generate_uuid()}
'project_id': uuidutils.generate_uuid(),
'id': uuidutils.generate_uuid()}
pool_dm = self.repos.create_pool_on_listener(self.session,
self.listener.id,
pool)
@ -258,9 +267,11 @@ class AllRepositoriesTest(base.OctaviaDBTestBase):
'description': 'desc1',
'lb_algorithm': constants.LB_ALGORITHM_ROUND_ROBIN,
'enabled': True, 'operating_status': constants.ONLINE,
'project_id': uuidutils.generate_uuid()}
'project_id': uuidutils.generate_uuid(),
'id': uuidutils.generate_uuid()}
sp = {'type': constants.SESSION_PERSISTENCE_HTTP_COOKIE,
'cookie_name': 'cookie_monster'}
'cookie_name': 'cookie_monster',
'pool_id': pool['id']}
pool_dm = self.repos.create_pool_on_listener(self.session,
self.listener.id,
pool, sp_dict=sp)