Merge "Add statistics to V2 API"
This commit is contained in:
commit
4652085d9a
@ -28,6 +28,7 @@ from octavia.api.v2.types import listener as listener_types
|
||||
from octavia.common import constants
|
||||
from octavia.common import data_models
|
||||
from octavia.common import exceptions
|
||||
from octavia.common import stats
|
||||
from octavia.db import api as db_api
|
||||
from octavia.db import prepare as db_prepare
|
||||
|
||||
@ -328,3 +329,41 @@ class ListenersController(base.BaseController):
|
||||
self.repositories.listener.update(
|
||||
lock_session, db_listener.id,
|
||||
provisioning_status=constants.ERROR)
|
||||
|
||||
@pecan.expose()
|
||||
def _lookup(self, id, *remainder):
|
||||
"""Overridden pecan _lookup method for custom routing.
|
||||
|
||||
Currently it checks if this was a stats request and routes
|
||||
the request to the StatsController.
|
||||
"""
|
||||
if id and len(remainder) and remainder[0] == 'stats':
|
||||
return StatisticsController(listener_id=id), remainder[1:]
|
||||
|
||||
|
||||
class StatisticsController(base.BaseController, stats.StatsMixin):
|
||||
RBAC_TYPE = constants.RBAC_LISTENER
|
||||
|
||||
def __init__(self, listener_id):
|
||||
super(StatisticsController, self).__init__()
|
||||
self.id = listener_id
|
||||
|
||||
@wsme_pecan.wsexpose(listener_types.StatisticsRootResponse, wtypes.text,
|
||||
status_code=200)
|
||||
def get(self):
|
||||
context = pecan.request.context.get('octavia_context')
|
||||
db_listener = self._get_db_listener(context.session, self.id)
|
||||
if not db_listener:
|
||||
LOG.info("Listener %s not found.", id)
|
||||
raise exceptions.NotFound(
|
||||
resource=data_models.Listener._name(),
|
||||
id=id)
|
||||
|
||||
self._auth_validate_action(context, db_listener.project_id,
|
||||
constants.RBAC_GET_STATS)
|
||||
|
||||
listener_stats = self.get_listener_stats(context.session, self.id)
|
||||
|
||||
result = self._convert_db_to_type(
|
||||
listener_stats, listener_types.ListenerStatisticsResponse)
|
||||
return listener_types.StatisticsRootResponse(stats=result)
|
||||
|
@ -29,6 +29,7 @@ from octavia.api.v2.types import load_balancer as lb_types
|
||||
from octavia.common import constants
|
||||
from octavia.common import data_models
|
||||
from octavia.common import exceptions
|
||||
from octavia.common import stats
|
||||
from octavia.common import utils
|
||||
import octavia.common.validate as validate
|
||||
from octavia.db import api as db_api
|
||||
@ -401,18 +402,24 @@ class LoadBalancersController(base.BaseController):
|
||||
Currently it checks if this was a statuses request and routes
|
||||
the request to the StatusesController.
|
||||
"""
|
||||
if id and len(remainder) and remainder[0] == 'statuses':
|
||||
return StatusesController(lb_id=id), remainder[1:]
|
||||
if id and len(remainder) and (remainder[0] == 'status' or
|
||||
remainder[0] == 'stats'):
|
||||
controller = remainder[0]
|
||||
remainder = remainder[1:]
|
||||
if controller == 'status':
|
||||
return StatusController(lb_id=id), remainder
|
||||
elif controller == 'stats':
|
||||
return StatisticsController(lb_id=id), remainder
|
||||
|
||||
|
||||
class StatusesController(base.BaseController):
|
||||
class StatusController(base.BaseController):
|
||||
RBAC_TYPE = constants.RBAC_LOADBALANCER
|
||||
|
||||
def __init__(self, lb_id):
|
||||
super(StatusesController, self).__init__()
|
||||
super(StatusController, self).__init__()
|
||||
self.id = lb_id
|
||||
|
||||
@wsme_pecan.wsexpose(lb_types.StatusesRootResponse, wtypes.text,
|
||||
@wsme_pecan.wsexpose(lb_types.StatusRootResponse, wtypes.text,
|
||||
status_code=200)
|
||||
def get(self):
|
||||
context = pecan.request.context.get('octavia_context')
|
||||
@ -427,6 +434,34 @@ class StatusesController(base.BaseController):
|
||||
constants.RBAC_GET_STATUS)
|
||||
|
||||
result = self._convert_db_to_type(
|
||||
load_balancer, lb_types.LoadBalancerStatusesResponse)
|
||||
result = lb_types.StatusesResponse(loadbalancer=result)
|
||||
return lb_types.StatusesRootResponse(statuses=result)
|
||||
load_balancer, lb_types.LoadBalancerStatusResponse)
|
||||
result = lb_types.StatusResponse(loadbalancer=result)
|
||||
return lb_types.StatusRootResponse(statuses=result)
|
||||
|
||||
|
||||
class StatisticsController(base.BaseController, stats.StatsMixin):
|
||||
RBAC_TYPE = constants.RBAC_LOADBALANCER
|
||||
|
||||
def __init__(self, lb_id):
|
||||
super(StatisticsController, self).__init__()
|
||||
self.id = lb_id
|
||||
|
||||
@wsme_pecan.wsexpose(lb_types.StatisticsRootResponse, wtypes.text,
|
||||
status_code=200)
|
||||
def get(self):
|
||||
context = pecan.request.context.get('octavia_context')
|
||||
load_balancer = self._get_db_lb(context.session, self.id)
|
||||
if not load_balancer:
|
||||
LOG.info("Load balancer %s not found.", id)
|
||||
raise exceptions.NotFound(
|
||||
resource=data_models.LoadBalancer._name(),
|
||||
id=id)
|
||||
|
||||
self._auth_validate_action(context, load_balancer.project_id,
|
||||
constants.RBAC_GET_STATS)
|
||||
|
||||
lb_stats = self.get_loadbalancer_stats(context.session, self.id)
|
||||
|
||||
result = self._convert_db_to_type(
|
||||
lb_stats, lb_types.LoadBalancerStatisticsResponse)
|
||||
return lb_types.StatisticsRootResponse(stats=result)
|
||||
|
@ -157,8 +157,8 @@ class HealthMonitorSingleCreate(BaseHealthMonitorType):
|
||||
admin_state_up = wtypes.wsattr(bool, default=True)
|
||||
|
||||
|
||||
class HealthMonitorStatusesResponse(BaseHealthMonitorType):
|
||||
"""Defines which attributes are to be shown on statuses response."""
|
||||
class HealthMonitorStatusResponse(BaseHealthMonitorType):
|
||||
"""Defines which attributes are to be shown on status response."""
|
||||
id = wtypes.wsattr(wtypes.UuidType())
|
||||
name = wtypes.wsattr(wtypes.StringType())
|
||||
type = wtypes.wsattr(wtypes.text)
|
||||
|
@ -156,20 +156,20 @@ class ListenerSingleCreate(BaseListenerType):
|
||||
wtypes.DictType(str, wtypes.StringType(max_length=255)))
|
||||
|
||||
|
||||
class ListenerStatusesResponse(BaseListenerType):
|
||||
"""Defines which attributes are to be shown on statuses response."""
|
||||
class ListenerStatusResponse(BaseListenerType):
|
||||
"""Defines which attributes are to be shown on status response."""
|
||||
id = wtypes.wsattr(wtypes.UuidType())
|
||||
name = wtypes.wsattr(wtypes.StringType())
|
||||
operating_status = wtypes.wsattr(wtypes.StringType())
|
||||
provisioning_status = wtypes.wsattr(wtypes.StringType())
|
||||
pools = wtypes.wsattr([pool.PoolStatusesResponse])
|
||||
pools = wtypes.wsattr([pool.PoolStatusResponse])
|
||||
|
||||
@classmethod
|
||||
def from_data_model(cls, data_model, children=False):
|
||||
listener = super(ListenerStatusesResponse, cls).from_data_model(
|
||||
listener = super(ListenerStatusResponse, cls).from_data_model(
|
||||
data_model, children=children)
|
||||
|
||||
pool_model = pool.PoolStatusesResponse
|
||||
pool_model = pool.PoolStatusResponse
|
||||
listener.pools = [
|
||||
pool_model.from_data_model(i) for i in data_model.pools]
|
||||
|
||||
@ -177,3 +177,22 @@ class ListenerStatusesResponse(BaseListenerType):
|
||||
listener.name = ""
|
||||
|
||||
return listener
|
||||
|
||||
|
||||
class ListenerStatisticsResponse(BaseListenerType):
|
||||
"""Defines which attributes are to show on stats response."""
|
||||
bytes_in = wtypes.wsattr(wtypes.IntegerType())
|
||||
bytes_out = wtypes.wsattr(wtypes.IntegerType())
|
||||
active_connections = wtypes.wsattr(wtypes.IntegerType())
|
||||
total_connections = wtypes.wsattr(wtypes.IntegerType())
|
||||
request_errors = wtypes.wsattr(wtypes.IntegerType())
|
||||
|
||||
@classmethod
|
||||
def from_data_model(cls, data_model, children=False):
|
||||
result = super(ListenerStatisticsResponse, cls).from_data_model(
|
||||
data_model, children=children)
|
||||
return result
|
||||
|
||||
|
||||
class StatisticsRootResponse(types.BaseType):
|
||||
stats = wtypes.wsattr(ListenerStatisticsResponse)
|
||||
|
@ -141,19 +141,19 @@ class LoadBalancerRootPUT(types.BaseType):
|
||||
loadbalancer = wtypes.wsattr(LoadBalancerPUT)
|
||||
|
||||
|
||||
class LoadBalancerStatusesResponse(BaseLoadBalancerType):
|
||||
"""Defines which attributes are to be shown on statuses response."""
|
||||
class LoadBalancerStatusResponse(BaseLoadBalancerType):
|
||||
"""Defines which attributes are to be shown on status response."""
|
||||
id = wtypes.wsattr(wtypes.UuidType())
|
||||
name = wtypes.wsattr(wtypes.StringType())
|
||||
operating_status = wtypes.wsattr(wtypes.StringType())
|
||||
provisioning_status = wtypes.wsattr(wtypes.StringType())
|
||||
listeners = wtypes.wsattr([listener.ListenerStatusesResponse])
|
||||
listeners = wtypes.wsattr([listener.ListenerStatusResponse])
|
||||
|
||||
@classmethod
|
||||
def from_data_model(cls, data_model, children=False):
|
||||
result = super(LoadBalancerStatusesResponse, cls).from_data_model(
|
||||
result = super(LoadBalancerStatusResponse, cls).from_data_model(
|
||||
data_model, children=children)
|
||||
listener_model = listener.ListenerStatusesResponse
|
||||
listener_model = listener.ListenerStatusResponse
|
||||
result.listeners = [
|
||||
listener_model.from_data_model(i) for i in data_model.listeners]
|
||||
if not result.name:
|
||||
@ -162,9 +162,28 @@ class LoadBalancerStatusesResponse(BaseLoadBalancerType):
|
||||
return result
|
||||
|
||||
|
||||
class StatusesResponse(wtypes.Base):
|
||||
loadbalancer = wtypes.wsattr(LoadBalancerStatusesResponse)
|
||||
class StatusResponse(wtypes.Base):
|
||||
loadbalancer = wtypes.wsattr(LoadBalancerStatusResponse)
|
||||
|
||||
|
||||
class StatusesRootResponse(types.BaseType):
|
||||
statuses = wtypes.wsattr(StatusesResponse)
|
||||
class StatusRootResponse(types.BaseType):
|
||||
statuses = wtypes.wsattr(StatusResponse)
|
||||
|
||||
|
||||
class LoadBalancerStatisticsResponse(BaseLoadBalancerType):
|
||||
"""Defines which attributes are to show on stats response."""
|
||||
bytes_in = wtypes.wsattr(wtypes.IntegerType())
|
||||
bytes_out = wtypes.wsattr(wtypes.IntegerType())
|
||||
active_connections = wtypes.wsattr(wtypes.IntegerType())
|
||||
total_connections = wtypes.wsattr(wtypes.IntegerType())
|
||||
request_errors = wtypes.wsattr(wtypes.IntegerType())
|
||||
|
||||
@classmethod
|
||||
def from_data_model(cls, data_model, children=False):
|
||||
result = super(LoadBalancerStatisticsResponse, cls).from_data_model(
|
||||
data_model, children=children)
|
||||
return result
|
||||
|
||||
|
||||
class StatisticsRootResponse(types.BaseType):
|
||||
stats = wtypes.wsattr(LoadBalancerStatisticsResponse)
|
||||
|
@ -114,8 +114,8 @@ class MemberSingleCreate(BaseMemberType):
|
||||
subnet_id = wtypes.wsattr(wtypes.UuidType())
|
||||
|
||||
|
||||
class MemberStatusesResponse(BaseMemberType):
|
||||
"""Defines which attributes are to be shown on statuses response."""
|
||||
class MemberStatusResponse(BaseMemberType):
|
||||
"""Defines which attributes are to be shown on status response."""
|
||||
id = wtypes.wsattr(wtypes.UuidType())
|
||||
name = wtypes.wsattr(wtypes.StringType())
|
||||
operating_status = wtypes.wsattr(wtypes.StringType())
|
||||
@ -125,7 +125,7 @@ class MemberStatusesResponse(BaseMemberType):
|
||||
|
||||
@classmethod
|
||||
def from_data_model(cls, data_model, children=False):
|
||||
member = super(MemberStatusesResponse, cls).from_data_model(
|
||||
member = super(MemberStatusResponse, cls).from_data_model(
|
||||
data_model, children=children)
|
||||
|
||||
if not member.name:
|
||||
|
@ -166,25 +166,25 @@ class PoolSingleCreate(BasePoolType):
|
||||
members = wtypes.wsattr([member.MemberSingleCreate])
|
||||
|
||||
|
||||
class PoolStatusesResponse(BasePoolType):
|
||||
"""Defines which attributes are to be shown on statuses response."""
|
||||
class PoolStatusResponse(BasePoolType):
|
||||
"""Defines which attributes are to be shown on status response."""
|
||||
id = wtypes.wsattr(wtypes.UuidType())
|
||||
name = wtypes.wsattr(wtypes.StringType())
|
||||
provisioning_status = wtypes.wsattr(wtypes.StringType())
|
||||
operating_status = wtypes.wsattr(wtypes.StringType())
|
||||
health_monitor = wtypes.wsattr(
|
||||
health_monitor.HealthMonitorStatusesResponse)
|
||||
members = wtypes.wsattr([member.MemberStatusesResponse])
|
||||
health_monitor.HealthMonitorStatusResponse)
|
||||
members = wtypes.wsattr([member.MemberStatusResponse])
|
||||
|
||||
@classmethod
|
||||
def from_data_model(cls, data_model, children=False):
|
||||
pool = super(PoolStatusesResponse, cls).from_data_model(
|
||||
pool = super(PoolStatusResponse, cls).from_data_model(
|
||||
data_model, children=children)
|
||||
|
||||
member_model = member.MemberStatusesResponse
|
||||
member_model = member.MemberStatusResponse
|
||||
if data_model.health_monitor:
|
||||
pool.health_monitor = (
|
||||
health_monitor.HealthMonitorStatusesResponse.from_data_model(
|
||||
health_monitor.HealthMonitorStatusResponse.from_data_model(
|
||||
data_model.health_monitor))
|
||||
pool.members = [
|
||||
member_model.from_data_model(i) for i in data_model.members]
|
||||
|
@ -189,6 +189,17 @@ class BaseAPITest(base_db_test.OctaviaDBTestBase):
|
||||
request_errors=0)
|
||||
return db_ls.to_dict()
|
||||
|
||||
def create_listener_stats_dynamic(self, listener_id, amphora_id,
|
||||
bytes_in=0, bytes_out=0,
|
||||
active_connections=0,
|
||||
total_connections=0, request_errors=0):
|
||||
db_ls = self.listener_stats_repo.create(
|
||||
db_api.get_session(), listener_id=listener_id,
|
||||
amphora_id=amphora_id, bytes_in=bytes_in,
|
||||
bytes_out=bytes_out, active_connections=active_connections,
|
||||
total_connections=total_connections, request_errors=request_errors)
|
||||
return db_ls.to_dict()
|
||||
|
||||
def create_amphora(self, amphora_id, loadbalancer_id, **optionals):
|
||||
# We need to default these values in the request.
|
||||
opts = {'compute_id': uuidutils.generate_uuid(),
|
||||
|
@ -14,6 +14,7 @@
|
||||
# under the License.
|
||||
|
||||
import mock
|
||||
import random
|
||||
|
||||
from oslo_config import cfg
|
||||
from oslo_config import fixture as oslo_fixture
|
||||
@ -1128,3 +1129,107 @@ class TestListener(base.BaseAPITest):
|
||||
'insert_headers': {'X-Forwarded-Four': 'true'}}
|
||||
body = self._build_body(lb_listener)
|
||||
self.post(self.LISTENERS_PATH, body, status=400)
|
||||
|
||||
def _getStats(self, listener_id):
|
||||
res = self.get(self.LISTENER_PATH.format(
|
||||
listener_id=listener_id + "/stats"))
|
||||
return res.json.get('stats')
|
||||
|
||||
def test_statistics(self):
|
||||
lb = self.create_load_balancer(
|
||||
uuidutils.generate_uuid()).get('loadbalancer')
|
||||
self.set_lb_status(lb['id'])
|
||||
li = self.create_listener(
|
||||
constants.PROTOCOL_HTTP, 80, lb.get('id')).get('listener')
|
||||
amphora = self.create_amphora(uuidutils.generate_uuid(), lb['id'])
|
||||
ls = self.create_listener_stats_dynamic(
|
||||
listener_id=li.get('id'),
|
||||
amphora_id=amphora.id,
|
||||
bytes_in=random.randint(1, 9),
|
||||
bytes_out=random.randint(1, 9),
|
||||
total_connections=random.randint(1, 9),
|
||||
request_errors=random.randint(1, 9))
|
||||
|
||||
response = self._getStats(li['id'])
|
||||
self.assertEqual(ls['bytes_in'], response['bytes_in'])
|
||||
self.assertEqual(ls['bytes_out'], response['bytes_out'])
|
||||
self.assertEqual(ls['total_connections'],
|
||||
response['total_connections'])
|
||||
self.assertEqual(ls['active_connections'],
|
||||
response['active_connections'])
|
||||
self.assertEqual(ls['request_errors'],
|
||||
response['request_errors'])
|
||||
|
||||
def test_statistics_authorized(self):
|
||||
project_id = uuidutils.generate_uuid()
|
||||
lb = self.create_load_balancer(
|
||||
uuidutils.generate_uuid(),
|
||||
project_id=project_id).get('loadbalancer')
|
||||
self.set_lb_status(lb['id'])
|
||||
li = self.create_listener(
|
||||
constants.PROTOCOL_HTTP, 80, lb.get('id')).get('listener')
|
||||
amphora = self.create_amphora(uuidutils.generate_uuid(), lb['id'])
|
||||
ls = self.create_listener_stats_dynamic(
|
||||
listener_id=li.get('id'),
|
||||
amphora_id=amphora.id,
|
||||
bytes_in=random.randint(1, 9),
|
||||
bytes_out=random.randint(1, 9),
|
||||
total_connections=random.randint(1, 9),
|
||||
request_errors=random.randint(1, 9))
|
||||
self.conf = self.useFixture(oslo_fixture.Config(cfg.CONF))
|
||||
auth_strategy = self.conf.conf.api_settings.get('auth_strategy')
|
||||
self.conf.config(group='api_settings', auth_strategy=constants.TESTING)
|
||||
|
||||
with mock.patch.object(octavia.common.context.Context, 'project_id',
|
||||
project_id):
|
||||
override_credentials = {
|
||||
'service_user_id': None,
|
||||
'user_domain_id': None,
|
||||
'is_admin_project': True,
|
||||
'service_project_domain_id': None,
|
||||
'service_project_id': None,
|
||||
'roles': ['load-balancer_member'],
|
||||
'user_id': None,
|
||||
'is_admin': False,
|
||||
'service_user_domain_id': None,
|
||||
'project_domain_id': None,
|
||||
'service_roles': [],
|
||||
'project_id': project_id}
|
||||
with mock.patch(
|
||||
"oslo_context.context.RequestContext.to_policy_values",
|
||||
return_value=override_credentials):
|
||||
response = self._getStats(li['id'])
|
||||
self.conf.config(group='api_settings', auth_strategy=auth_strategy)
|
||||
|
||||
self.assertEqual(ls['bytes_in'], response['bytes_in'])
|
||||
self.assertEqual(ls['bytes_out'], response['bytes_out'])
|
||||
self.assertEqual(ls['total_connections'],
|
||||
response['total_connections'])
|
||||
self.assertEqual(ls['active_connections'],
|
||||
response['active_connections'])
|
||||
self.assertEqual(ls['request_errors'],
|
||||
response['request_errors'])
|
||||
|
||||
def test_statistics_not_authorized(self):
|
||||
lb = self.create_load_balancer(
|
||||
uuidutils.generate_uuid()).get('loadbalancer')
|
||||
self.set_lb_status(lb['id'])
|
||||
li = self.create_listener(
|
||||
constants.PROTOCOL_HTTP, 80, lb.get('id')).get('listener')
|
||||
amphora = self.create_amphora(uuidutils.generate_uuid(), lb['id'])
|
||||
self.create_listener_stats_dynamic(
|
||||
listener_id=li.get('id'),
|
||||
amphora_id=amphora.id,
|
||||
bytes_in=random.randint(1, 9),
|
||||
bytes_out=random.randint(1, 9),
|
||||
total_connections=random.randint(1, 9),
|
||||
request_errors=random.randint(1, 9))
|
||||
self.conf = self.useFixture(oslo_fixture.Config(cfg.CONF))
|
||||
auth_strategy = self.conf.conf.api_settings.get('auth_strategy')
|
||||
self.conf.config(group='api_settings', auth_strategy=constants.TESTING)
|
||||
with mock.patch.object(octavia.common.context.Context, 'project_id',
|
||||
uuidutils.generate_uuid()):
|
||||
res = self.get(self.LISTENER_PATH.format(
|
||||
listener_id=li['id'] + "/stats"), status=403)
|
||||
self.conf.config(group='api_settings', auth_strategy=auth_strategy)
|
||||
self.assertEqual(self.NOT_AUTHORIZED_BODY, res.json)
|
||||
|
@ -13,6 +13,7 @@
|
||||
# under the License.
|
||||
|
||||
import copy
|
||||
import random
|
||||
|
||||
import mock
|
||||
from oslo_config import cfg
|
||||
@ -1827,7 +1828,7 @@ class TestLoadBalancerGraph(base.BaseAPITest):
|
||||
self.post(self.LBS_PATH, body)
|
||||
|
||||
def _getStatus(self, lb_id):
|
||||
res = self.get(self.LB_PATH.format(lb_id=lb_id + "/statuses"))
|
||||
res = self.get(self.LB_PATH.format(lb_id=lb_id + "/status"))
|
||||
return res.json.get('statuses').get('loadbalancer')
|
||||
|
||||
def test_statuses(self):
|
||||
@ -2122,7 +2123,111 @@ class TestLoadBalancerGraph(base.BaseAPITest):
|
||||
with mock.patch.object(octavia.common.context.Context, 'project_id',
|
||||
uuidutils.generate_uuid()):
|
||||
|
||||
res = self.get(self.LB_PATH.format(lb_id=lb['id'] + "/statuses"),
|
||||
res = self.get(self.LB_PATH.format(lb_id=lb['id'] + "/status"),
|
||||
status=403)
|
||||
self.conf.config(group='api_settings', auth_strategy=auth_strategy)
|
||||
self.assertEqual(self.NOT_AUTHORIZED_BODY, res.json)
|
||||
|
||||
def _getStats(self, lb_id):
|
||||
res = self.get(self.LB_PATH.format(lb_id=lb_id + "/stats"))
|
||||
return res.json.get('stats')
|
||||
|
||||
def test_statistics(self):
|
||||
lb = self.create_load_balancer(
|
||||
uuidutils.generate_uuid()).get('loadbalancer')
|
||||
self.set_lb_status(lb['id'])
|
||||
li = self.create_listener(
|
||||
constants.PROTOCOL_HTTP, 80, lb.get('id')).get('listener')
|
||||
amphora = self.create_amphora(uuidutils.generate_uuid(), lb['id'])
|
||||
ls = self.create_listener_stats_dynamic(
|
||||
listener_id=li.get('id'),
|
||||
amphora_id=amphora.id,
|
||||
bytes_in=random.randint(1, 9),
|
||||
bytes_out=random.randint(1, 9),
|
||||
total_connections=random.randint(1, 9),
|
||||
request_errors=random.randint(1, 9))
|
||||
|
||||
response = self._getStats(lb['id'])
|
||||
self.assertEqual(ls['bytes_in'], response['bytes_in'])
|
||||
self.assertEqual(ls['bytes_out'], response['bytes_out'])
|
||||
self.assertEqual(ls['total_connections'],
|
||||
response['total_connections'])
|
||||
self.assertEqual(ls['active_connections'],
|
||||
response['active_connections'])
|
||||
self.assertEqual(ls['request_errors'],
|
||||
response['request_errors'])
|
||||
|
||||
def test_statistics_authorized(self):
|
||||
project_id = uuidutils.generate_uuid()
|
||||
lb = self.create_load_balancer(
|
||||
uuidutils.generate_uuid(),
|
||||
project_id=project_id).get('loadbalancer')
|
||||
self.set_lb_status(lb['id'])
|
||||
li = self.create_listener(
|
||||
constants.PROTOCOL_HTTP, 80, lb.get('id')).get('listener')
|
||||
amphora = self.create_amphora(uuidutils.generate_uuid(), lb['id'])
|
||||
ls = self.create_listener_stats_dynamic(
|
||||
listener_id=li.get('id'),
|
||||
amphora_id=amphora.id,
|
||||
bytes_in=random.randint(1, 9),
|
||||
bytes_out=random.randint(1, 9),
|
||||
total_connections=random.randint(1, 9),
|
||||
request_errors=random.randint(1, 9))
|
||||
|
||||
self.conf = self.useFixture(oslo_fixture.Config(cfg.CONF))
|
||||
auth_strategy = self.conf.conf.api_settings.get('auth_strategy')
|
||||
self.conf.config(group='api_settings', auth_strategy=constants.TESTING)
|
||||
|
||||
with mock.patch.object(octavia.common.context.Context, 'project_id',
|
||||
project_id):
|
||||
override_credentials = {
|
||||
'service_user_id': None,
|
||||
'user_domain_id': None,
|
||||
'is_admin_project': True,
|
||||
'service_project_domain_id': None,
|
||||
'service_project_id': None,
|
||||
'roles': ['load-balancer_member'],
|
||||
'user_id': None,
|
||||
'is_admin': False,
|
||||
'service_user_domain_id': None,
|
||||
'project_domain_id': None,
|
||||
'service_roles': [],
|
||||
'project_id': project_id}
|
||||
with mock.patch(
|
||||
"oslo_context.context.RequestContext.to_policy_values",
|
||||
return_value=override_credentials):
|
||||
response = self._getStats(lb['id'])
|
||||
self.conf.config(group='api_settings', auth_strategy=auth_strategy)
|
||||
|
||||
self.assertEqual(ls['bytes_in'], response['bytes_in'])
|
||||
self.assertEqual(ls['bytes_out'], response['bytes_out'])
|
||||
self.assertEqual(ls['total_connections'],
|
||||
response['total_connections'])
|
||||
self.assertEqual(ls['active_connections'],
|
||||
response['active_connections'])
|
||||
self.assertEqual(ls['request_errors'],
|
||||
response['request_errors'])
|
||||
|
||||
def test_statistics_not_authorized(self):
|
||||
lb = self.create_load_balancer(
|
||||
uuidutils.generate_uuid()).get('loadbalancer')
|
||||
self.set_lb_status(lb['id'])
|
||||
li = self.create_listener(
|
||||
constants.PROTOCOL_HTTP, 80, lb.get('id')).get('listener')
|
||||
amphora = self.create_amphora(uuidutils.generate_uuid(), lb['id'])
|
||||
self.create_listener_stats_dynamic(
|
||||
listener_id=li.get('id'),
|
||||
amphora_id=amphora.id,
|
||||
bytes_in=random.randint(1, 9),
|
||||
bytes_out=random.randint(1, 9),
|
||||
total_connections=random.randint(1, 9))
|
||||
self.conf = self.useFixture(oslo_fixture.Config(cfg.CONF))
|
||||
auth_strategy = self.conf.conf.api_settings.get('auth_strategy')
|
||||
self.conf.config(group='api_settings', auth_strategy=constants.TESTING)
|
||||
with mock.patch.object(octavia.common.context.Context, 'project_id',
|
||||
uuidutils.generate_uuid()):
|
||||
res = self.get(self.LB_PATH.format(lb_id=lb['id'] + "/stats"),
|
||||
status=403)
|
||||
|
||||
self.conf.config(group='api_settings', auth_strategy=auth_strategy)
|
||||
self.assertEqual(self.NOT_AUTHORIZED_BODY, res.json)
|
||||
|
Loading…
Reference in New Issue
Block a user