Metering LoadBalancer as a Service
This adds support for measurements around LBaaS. Added Pollsters to track Load balancer Pools, Vips, members and Health Probes. Also includes statistics pollsters to track total_connections, active_connections and bandwidth. Included test coverage for Neutron client and LBaaS pollsters. Change-Id: Ia0570a824e099c341c8f12f95f576dfb8b1fdfc4 Partially Implements: blueprint ceilometer-meter-lbaas
This commit is contained in:
parent
a30beaacfa
commit
3add1f7832
0
ceilometer/network/services/__init__.py
Normal file
0
ceilometer/network/services/__init__.py
Normal file
346
ceilometer/network/services/lbaas.py
Normal file
346
ceilometer/network/services/lbaas.py
Normal file
@ -0,0 +1,346 @@
|
||||
#
|
||||
# Copyright 2014 Cisco Systems,Inc.
|
||||
#
|
||||
# Author: Pradeep Kilambi <pkilambi@cisco.com>
|
||||
#
|
||||
# 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
|
||||
import collections
|
||||
import six
|
||||
|
||||
from ceilometer import neutron_client
|
||||
from ceilometer.openstack.common.gettextutils import _
|
||||
from ceilometer.openstack.common import log
|
||||
from ceilometer.openstack.common import timeutils
|
||||
from ceilometer import plugin
|
||||
from ceilometer import sample
|
||||
|
||||
LOG = log.getLogger(__name__)
|
||||
|
||||
LBStatsData = collections.namedtuple(
|
||||
'LBStats',
|
||||
['active_connections', 'total_connections', 'bytes_in', 'bytes_out']
|
||||
)
|
||||
|
||||
# status map for converting metric status to volume int
|
||||
STATUS = {
|
||||
'inactive': 0,
|
||||
'active': 1,
|
||||
'pending_create': 2,
|
||||
}
|
||||
|
||||
|
||||
class _BasePollster(plugin.PollsterBase):
|
||||
|
||||
FIELDS = []
|
||||
nc = neutron_client.Client()
|
||||
|
||||
def _iter_cache(self, cache, meter_name, method):
|
||||
if meter_name not in cache:
|
||||
cache[meter_name] = list(method())
|
||||
return iter(cache[meter_name])
|
||||
|
||||
def extract_metadata(self, metric):
|
||||
return dict((k, metric[k]) for k in self.FIELDS)
|
||||
|
||||
@staticmethod
|
||||
def get_status_id(value):
|
||||
status = value.lower()
|
||||
if status not in STATUS:
|
||||
return -1
|
||||
return STATUS[status]
|
||||
|
||||
|
||||
class LBPoolPollster(_BasePollster):
|
||||
"""Pollster to capture Load Balancer pool status samples.
|
||||
"""
|
||||
FIELDS = ['admin_state_up',
|
||||
'description',
|
||||
'lb_method',
|
||||
'name',
|
||||
'protocol',
|
||||
'provider',
|
||||
'status',
|
||||
'status_description',
|
||||
'subnet_id',
|
||||
'vip_id'
|
||||
]
|
||||
|
||||
def _get_lb_pools(self):
|
||||
return self.nc.pool_get_all()
|
||||
|
||||
def get_samples(self, manager, cache, resources=None):
|
||||
for pool in self._iter_cache(cache, 'pool', self._get_lb_pools):
|
||||
LOG.debug("Load Balancer Pool : %s" % pool)
|
||||
status = self.get_status_id(pool['status'])
|
||||
if status == -1:
|
||||
# unknown status, skip this sample
|
||||
LOG.warn("Unknown status %s received on pool %s, "
|
||||
"skipping sample" % (pool['status'], pool['id']))
|
||||
continue
|
||||
|
||||
yield sample.Sample(
|
||||
name='network.services.lb.pool',
|
||||
type=sample.TYPE_GAUGE,
|
||||
unit='pool',
|
||||
volume=status,
|
||||
user_id=None,
|
||||
project_id=pool['tenant_id'],
|
||||
resource_id=pool['id'],
|
||||
timestamp=timeutils.utcnow().isoformat(),
|
||||
resource_metadata=self.extract_metadata(pool)
|
||||
)
|
||||
|
||||
|
||||
class LBVipPollster(_BasePollster):
|
||||
"""Pollster to capture Load Balancer Vip status samples.
|
||||
"""
|
||||
FIELDS = ['admin_state_up',
|
||||
'address',
|
||||
'connection_limit',
|
||||
'description',
|
||||
'name',
|
||||
'pool_id',
|
||||
'port_id',
|
||||
'protocol',
|
||||
'protocol_port',
|
||||
'status',
|
||||
'status_description',
|
||||
'subnet_id',
|
||||
'session_persistence',
|
||||
]
|
||||
|
||||
def _get_lb_vips(self):
|
||||
return self.nc.vip_get_all()
|
||||
|
||||
def get_samples(self, manager, cache, resources=None):
|
||||
for vip in self._iter_cache(cache, 'vip', self._get_lb_vips):
|
||||
LOG.debug("Load Balancer Vip : %s" % vip)
|
||||
status = self.get_status_id(vip['status'])
|
||||
if status == -1:
|
||||
# unknown status, skip this sample
|
||||
LOG.warn("Unknown status %s received on vip %s, "
|
||||
"skipping sample" % (vip['status'], vip['id']))
|
||||
continue
|
||||
|
||||
yield sample.Sample(
|
||||
name='network.services.lb.vip',
|
||||
type=sample.TYPE_GAUGE,
|
||||
unit='vip',
|
||||
volume=status,
|
||||
user_id=None,
|
||||
project_id=vip['tenant_id'],
|
||||
resource_id=vip['id'],
|
||||
timestamp=timeutils.utcnow().isoformat(),
|
||||
resource_metadata=self.extract_metadata(vip)
|
||||
)
|
||||
|
||||
|
||||
class LBMemberPollster(_BasePollster):
|
||||
"""Pollster to capture Load Balancer Member status samples.
|
||||
"""
|
||||
FIELDS = ['admin_state_up',
|
||||
'address',
|
||||
'pool_id',
|
||||
'protocol_port',
|
||||
'status',
|
||||
'status_description',
|
||||
'weight',
|
||||
]
|
||||
|
||||
def _get_lb_members(self):
|
||||
return self.nc.member_get_all()
|
||||
|
||||
def get_samples(self, manager, cache, resources=None):
|
||||
for member in self._iter_cache(cache, 'member', self._get_lb_members):
|
||||
LOG.debug("Load Balancer Member : %s" % member)
|
||||
status = self.get_status_id(member['status'])
|
||||
if status == -1:
|
||||
LOG.warn("Unknown status %s received on member %s, "
|
||||
"skipping sample" % (member['status'], member['id']))
|
||||
continue
|
||||
yield sample.Sample(
|
||||
name='network.services.lb.member',
|
||||
type=sample.TYPE_GAUGE,
|
||||
unit='member',
|
||||
volume=status,
|
||||
user_id=None,
|
||||
project_id=member['tenant_id'],
|
||||
resource_id=member['id'],
|
||||
timestamp=timeutils.utcnow().isoformat(),
|
||||
resource_metadata=self.extract_metadata(member)
|
||||
)
|
||||
|
||||
|
||||
class LBHealthMonitorPollster(_BasePollster):
|
||||
"""Pollster to capture Load Balancer Health probes status samples.
|
||||
"""
|
||||
FIELDS = ['admin_state_up',
|
||||
'delay',
|
||||
'max_retries',
|
||||
'pools',
|
||||
'timeout',
|
||||
'type'
|
||||
]
|
||||
|
||||
def _get_lb_health_probes(self):
|
||||
return self.nc.health_monitor_get_all()
|
||||
|
||||
def get_samples(self, manager, cache, resources=None):
|
||||
for probe in self._iter_cache(cache, 'monitor',
|
||||
self._get_lb_health_probes):
|
||||
LOG.debug("Load Balancer Health probe : %s" % probe)
|
||||
yield sample.Sample(
|
||||
name='network.services.lb.health_monitor',
|
||||
type=sample.TYPE_GAUGE,
|
||||
unit='monitor',
|
||||
volume=1,
|
||||
user_id=None,
|
||||
project_id=probe['tenant_id'],
|
||||
resource_id=probe['id'],
|
||||
timestamp=timeutils.utcnow().isoformat(),
|
||||
resource_metadata=self.extract_metadata(probe)
|
||||
)
|
||||
|
||||
|
||||
@six.add_metaclass(abc.ABCMeta)
|
||||
class _LBStatsPollster(_BasePollster):
|
||||
"""Base Statistics pollster capturing the statistics info
|
||||
and yielding samples for connections and bandwidth.
|
||||
"""
|
||||
|
||||
def _get_lb_pools(self):
|
||||
return self.nc.pool_get_all()
|
||||
|
||||
def _get_pool_stats(self, pool_id):
|
||||
return self.nc.pool_stats(pool_id)
|
||||
|
||||
@staticmethod
|
||||
def make_sample_from_pool(pool, name, type, unit, volume,
|
||||
resource_metadata=None):
|
||||
if not resource_metadata:
|
||||
resource_metadata = {}
|
||||
return sample.Sample(
|
||||
name=name,
|
||||
type=type,
|
||||
unit=unit,
|
||||
volume=volume,
|
||||
user_id=None,
|
||||
project_id=pool['tenant_id'],
|
||||
resource_id=pool['id'],
|
||||
timestamp=timeutils.isotime(),
|
||||
resource_metadata=resource_metadata,
|
||||
)
|
||||
|
||||
def _populate_stats_cache(self, pool_id, cache):
|
||||
i_cache = cache.setdefault("lbstats", {})
|
||||
if pool_id not in i_cache:
|
||||
stats = self._get_pool_stats(pool_id)['stats']
|
||||
i_cache[pool_id] = LBStatsData(
|
||||
active_connections=stats['active_connections'],
|
||||
total_connections=stats['total_connections'],
|
||||
bytes_in=stats['bytes_in'],
|
||||
bytes_out=stats['bytes_out'],
|
||||
)
|
||||
return i_cache[pool_id]
|
||||
|
||||
@abc.abstractmethod
|
||||
def _get_sample(pool, c_data):
|
||||
"""Return one Sample."""
|
||||
|
||||
def get_samples(self, manager, cache, resources=None):
|
||||
for pool in self._get_lb_pools():
|
||||
try:
|
||||
c_data = self._populate_stats_cache(pool['id'], cache)
|
||||
yield self._get_sample(pool, c_data)
|
||||
except Exception as err:
|
||||
LOG.exception(_('Ignoring pool %(pool_id)s: %(error)s'),
|
||||
{'pool_id': pool['id'], 'error': err})
|
||||
|
||||
|
||||
class LBActiveConnectionsPollster(_LBStatsPollster):
|
||||
"""Pollster to capture Active Load Balancer connections.
|
||||
"""
|
||||
|
||||
@staticmethod
|
||||
def _get_sample(pool, data):
|
||||
return make_sample_from_pool(
|
||||
pool,
|
||||
name='network.services.lb.active.connections',
|
||||
type=sample.TYPE_GAUGE,
|
||||
unit='connection',
|
||||
volume=data.active_connections,
|
||||
)
|
||||
|
||||
|
||||
class LBTotalConnectionsPollster(_LBStatsPollster):
|
||||
"""Pollster to capture Total Load Balancer connections
|
||||
"""
|
||||
|
||||
@staticmethod
|
||||
def _get_sample(pool, data):
|
||||
return make_sample_from_pool(
|
||||
pool,
|
||||
name='network.services.lb.total.connections',
|
||||
type=sample.TYPE_GAUGE,
|
||||
unit='connection',
|
||||
volume=data.total_connections,
|
||||
)
|
||||
|
||||
|
||||
class LBBytesInPollster(_LBStatsPollster):
|
||||
"""Pollster to capture incoming bytes.
|
||||
"""
|
||||
|
||||
@staticmethod
|
||||
def _get_sample(pool, data):
|
||||
return make_sample_from_pool(
|
||||
pool,
|
||||
name='network.services.lb.incoming.bytes',
|
||||
type=sample.TYPE_GAUGE,
|
||||
unit='B',
|
||||
volume=data.bytes_in,
|
||||
)
|
||||
|
||||
|
||||
class LBBytesOutPollster(_LBStatsPollster):
|
||||
"""Pollster to capture outgoing bytes.
|
||||
"""
|
||||
|
||||
@staticmethod
|
||||
def _get_sample(pool, data):
|
||||
return make_sample_from_pool(
|
||||
pool,
|
||||
name='network.services.lb.outgoing.bytes',
|
||||
type=sample.TYPE_GAUGE,
|
||||
unit='B',
|
||||
volume=data.bytes_out,
|
||||
)
|
||||
|
||||
|
||||
def make_sample_from_pool(pool, name, type, unit, volume,
|
||||
resource_metadata=None):
|
||||
resource_metadata = resource_metadata or {}
|
||||
|
||||
return sample.Sample(
|
||||
name=name,
|
||||
type=type,
|
||||
unit=unit,
|
||||
volume=volume,
|
||||
user_id=None,
|
||||
project_id=pool['tenant_id'],
|
||||
resource_id=pool['id'],
|
||||
timestamp=timeutils.isotime(),
|
||||
resource_metadata=resource_metadata,
|
||||
)
|
@ -71,3 +71,27 @@ class Client(object):
|
||||
def port_get_all(self):
|
||||
resp = self.client.list_ports()
|
||||
return resp.get('ports')
|
||||
|
||||
@logged
|
||||
def vip_get_all(self):
|
||||
resp = self.client.list_vips()
|
||||
return resp.get('vips')
|
||||
|
||||
@logged
|
||||
def pool_get_all(self):
|
||||
resp = self.client.list_pools()
|
||||
return resp.get('pools')
|
||||
|
||||
@logged
|
||||
def member_get_all(self):
|
||||
resp = self.client.list_members()
|
||||
return resp.get('members')
|
||||
|
||||
@logged
|
||||
def health_monitor_get_all(self):
|
||||
resp = self.client.list_health_monitors()
|
||||
return resp.get('health_monitors')
|
||||
|
||||
@logged
|
||||
def pool_stats(self, pool):
|
||||
return self.client.retrieve_pool_stats(pool)
|
||||
|
0
ceilometer/tests/network/services/__init__.py
Normal file
0
ceilometer/tests/network/services/__init__.py
Normal file
399
ceilometer/tests/network/services/test_lbaas.py
Normal file
399
ceilometer/tests/network/services/test_lbaas.py
Normal file
@ -0,0 +1,399 @@
|
||||
#
|
||||
# Copyright 2014 Cisco Systems,Inc.
|
||||
#
|
||||
# Author: Pradeep Kilambi <pkilambi@cisco.com>
|
||||
#
|
||||
# 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 mock
|
||||
|
||||
from ceilometer.central import manager
|
||||
from ceilometer.network.services import lbaas
|
||||
from ceilometer.openstack.common import context
|
||||
from ceilometer.openstack.common.fixture import mockpatch
|
||||
from ceilometer.openstack.common import test
|
||||
|
||||
|
||||
class _BaseTestLBPollster(test.BaseTestCase):
|
||||
|
||||
@mock.patch('ceilometer.pipeline.setup_pipeline', mock.MagicMock())
|
||||
def setUp(self):
|
||||
super(_BaseTestLBPollster, self).setUp()
|
||||
self.addCleanup(mock.patch.stopall)
|
||||
self.context = context.get_admin_context()
|
||||
self.manager = manager.AgentManager()
|
||||
|
||||
|
||||
class TestLBPoolPollster(_BaseTestLBPollster):
|
||||
|
||||
def setUp(self):
|
||||
super(TestLBPoolPollster, self).setUp()
|
||||
self.pollster = lbaas.LBPoolPollster()
|
||||
fake_pools = self.fake_get_pools()
|
||||
self.useFixture(mockpatch.Patch('ceilometer.neutron_client.Client.'
|
||||
'pool_get_all',
|
||||
return_value=fake_pools))
|
||||
|
||||
@staticmethod
|
||||
def fake_get_pools():
|
||||
return [{'status': 'ACTIVE',
|
||||
'lb_method': 'ROUND_ROBIN',
|
||||
'protocol': 'HTTP',
|
||||
'description': '',
|
||||
'health_monitors': [],
|
||||
'members': [],
|
||||
'provider': 'haproxy',
|
||||
'status_description': None,
|
||||
'id': 'ce73ad36-437d-4c84-aee1-186027d3da9a',
|
||||
'vip_id': 'cd6a6fee-e2fa-4e6c-b3c2-bfbe395752c1',
|
||||
'name': 'mylb',
|
||||
'admin_state_up': True,
|
||||
'subnet_id': 'bbe3d818-bdcb-4e4b-b47f-5650dc8a9d7a',
|
||||
'tenant_id': 'a4eb9f4938bb418bbc4f8eb31802fefa',
|
||||
'health_monitors_status': []},
|
||||
{'status': 'INACTIVE',
|
||||
'lb_method': 'ROUND_ROBIN',
|
||||
'protocol': 'HTTP',
|
||||
'description': '',
|
||||
'health_monitors': [],
|
||||
'members': [],
|
||||
'provider': 'haproxy',
|
||||
'status_description': None,
|
||||
'id': 'ce73ad36-437d-4c84-aee1-186027d3da9a',
|
||||
'vip_id': 'cd6a6fee-e2fa-4e6c-b3c2-bfbe395752c1',
|
||||
'name': 'mylb02',
|
||||
'admin_state_up': True,
|
||||
'subnet_id': 'bbe3d818-bdcb-4e4b-b47f-5650dc8a9d7a',
|
||||
'tenant_id': 'a4eb9f4938bb418bbc4f8eb31802fefa',
|
||||
'health_monitors_status': []},
|
||||
{'status': 'PENDING_CREATE',
|
||||
'lb_method': 'ROUND_ROBIN',
|
||||
'protocol': 'HTTP',
|
||||
'description': '',
|
||||
'health_monitors': [],
|
||||
'members': [],
|
||||
'provider': 'haproxy',
|
||||
'status_description': None,
|
||||
'id': 'fe7rad36-437d-4c84-aee1-186027d3bdcd',
|
||||
'vip_id': 'cd6a6fee-e2fa-4e6c-b3c2-bfbe395752c1',
|
||||
'name': 'mylb03',
|
||||
'admin_state_up': True,
|
||||
'subnet_id': 'bbe3d818-bdcb-4e4b-b47f-5650dc8a9d7a',
|
||||
'tenant_id': 'a4eb9f4938bb418bbc4f8eb31802fefa',
|
||||
'health_monitors_status': []},
|
||||
{'status': 'UNKNOWN',
|
||||
'lb_method': 'ROUND_ROBIN',
|
||||
'protocol': 'HTTP',
|
||||
'description': '',
|
||||
'health_monitors': [],
|
||||
'members': [],
|
||||
'provider': 'haproxy',
|
||||
'status_description': None,
|
||||
'id': 'fe7rad36-437d-4c84-aee1-186027d3bdcd',
|
||||
'vip_id': 'cd6a6fee-e2fa-4e6c-b3c2-bfbe395752c1',
|
||||
'name': 'mylb03',
|
||||
'admin_state_up': True,
|
||||
'subnet_id': 'bbe3d818-bdcb-4e4b-b47f-5650dc8a9d7a',
|
||||
'tenant_id': 'a4eb9f4938bb418bbc4f8eb31802fefa',
|
||||
'health_monitors_status': []},
|
||||
]
|
||||
|
||||
def test_pool_get_samples(self):
|
||||
samples = list(self.pollster.get_samples(self.manager, {}))
|
||||
self.assertEqual(3, len(samples))
|
||||
for field in self.pollster.FIELDS:
|
||||
self.assertEqual(self.fake_get_pools()[0][field],
|
||||
samples[0].resource_metadata[field])
|
||||
|
||||
def test_pool_volume(self):
|
||||
samples = list(self.pollster.get_samples(self.manager, {}))
|
||||
self.assertEqual(1, samples[0].volume)
|
||||
self.assertEqual(0, samples[1].volume)
|
||||
self.assertEqual(2, samples[2].volume)
|
||||
|
||||
def test_get_pool_meter_names(self):
|
||||
samples = list(self.pollster.get_samples(self.manager, {}))
|
||||
self.assertEqual(set(['network.services.lb.pool']),
|
||||
set([s.name for s in samples]))
|
||||
|
||||
|
||||
class TestLBVipPollster(_BaseTestLBPollster):
|
||||
|
||||
def setUp(self):
|
||||
super(TestLBVipPollster, self).setUp()
|
||||
self.pollster = lbaas.LBVipPollster()
|
||||
fake_vips = self.fake_get_vips()
|
||||
self.useFixture(mockpatch.Patch('ceilometer.neutron_client.Client.'
|
||||
'vip_get_all',
|
||||
return_value=fake_vips))
|
||||
|
||||
@staticmethod
|
||||
def fake_get_vips():
|
||||
return [{'status': 'ACTIVE',
|
||||
'status_description': None,
|
||||
'protocol': 'HTTP',
|
||||
'description': '',
|
||||
'admin_state_up': True,
|
||||
'subnet_id': 'bbe3d818-bdcb-4e4b-b47f-5650dc8a9d7a',
|
||||
'tenant_id': 'a4eb9f4938bb418bbc4f8eb31802fefa',
|
||||
'connection_limit': -1,
|
||||
'pool_id': 'ce73ad36-437d-4c84-aee1-186027d3da9a',
|
||||
'session_persistence': None,
|
||||
'address': '10.0.0.2',
|
||||
'protocol_port': 80,
|
||||
'port_id': '3df3c4de-b32e-4ca1-a7f4-84323ba5f291',
|
||||
'id': 'cd6a6fee-e2fa-4e6c-b3c2-bfbe395752c1',
|
||||
'name': 'myvip'},
|
||||
{'status': 'INACTIVE',
|
||||
'status_description': None,
|
||||
'protocol': 'HTTP',
|
||||
'description': '',
|
||||
'admin_state_up': True,
|
||||
'subnet_id': 'bbe3d818-bdcb-4e4b-b47f-5650dc8a9d7a',
|
||||
'tenant_id': 'a4eb9f4938bb418bbc4f8eb31802fefa',
|
||||
'connection_limit': -1,
|
||||
'pool_id': 'ce73ad36-437d-4c84-aee1-186027d3da9a',
|
||||
'session_persistence': None,
|
||||
'address': '10.0.0.3',
|
||||
'protocol_port': 80,
|
||||
'port_id': '3df3c4de-b32e-4ca1-a7f4-84323ba5f291',
|
||||
'id': 'ba6a6fee-e2fa-4e6c-b3c2-bfbe395752c1',
|
||||
'name': 'myvip02'},
|
||||
{'status': 'PENDING_CREATE',
|
||||
'status_description': None,
|
||||
'protocol': 'HTTP',
|
||||
'description': '',
|
||||
'admin_state_up': True,
|
||||
'subnet_id': 'bbe3d818-bdcb-4e4b-b47f-5650dc8a9d7a',
|
||||
'tenant_id': 'a4eb9f4938bb418bbc4f8eb31802fefa',
|
||||
'connection_limit': -1,
|
||||
'pool_id': 'ce73ad36-437d-4c84-aee1-186027d3da9a',
|
||||
'session_persistence': None,
|
||||
'address': '10.0.0.4',
|
||||
'protocol_port': 80,
|
||||
'port_id': '3df3c4de-b32e-4ca1-a7f4-84323ba5f291',
|
||||
'id': 'fg6a6fee-e2fa-4e6c-b3c2-bfbe395752c1',
|
||||
'name': 'myvip03'},
|
||||
{'status': 'UNKNOWN',
|
||||
'status_description': None,
|
||||
'protocol': 'HTTP',
|
||||
'description': '',
|
||||
'admin_state_up': True,
|
||||
'subnet_id': 'bbe3d818-bdcb-4e4b-b47f-5650dc8a9d7a',
|
||||
'tenant_id': 'a4eb9f4938bb418bbc4f8eb31802fefa',
|
||||
'connection_limit': -1,
|
||||
'pool_id': 'ce73ad36-437d-4c84-aee1-186027d3da9a',
|
||||
'session_persistence': None,
|
||||
'address': '10.0.0.8',
|
||||
'protocol_port': 80,
|
||||
'port_id': '3df3c4de-b32e-4ca1-a7f4-84323ba5f291',
|
||||
'id': 'fg6a6fee-e2fa-4e6c-b3c2-bfbe395752c1',
|
||||
'name': 'myvip03'},
|
||||
]
|
||||
|
||||
def test_vip_get_samples(self):
|
||||
samples = list(self.pollster.get_samples(self.manager, {}))
|
||||
self.assertEqual(3, len(samples))
|
||||
for field in self.pollster.FIELDS:
|
||||
self.assertEqual(self.fake_get_vips()[0][field],
|
||||
samples[0].resource_metadata[field])
|
||||
|
||||
def test_pool_volume(self):
|
||||
samples = list(self.pollster.get_samples(self.manager, {}))
|
||||
self.assertEqual(1, samples[0].volume)
|
||||
self.assertEqual(0, samples[1].volume)
|
||||
self.assertEqual(2, samples[2].volume)
|
||||
|
||||
def test_get_vip_meter_names(self):
|
||||
samples = list(self.pollster.get_samples(self.manager, {}))
|
||||
self.assertEqual(set(['network.services.lb.vip']),
|
||||
set([s.name for s in samples]))
|
||||
|
||||
|
||||
class TestLBMemberPollster(_BaseTestLBPollster):
|
||||
|
||||
def setUp(self):
|
||||
super(TestLBMemberPollster, self).setUp()
|
||||
self.pollster = lbaas.LBMemberPollster()
|
||||
fake_members = self.fake_get_members()
|
||||
self.useFixture(mockpatch.Patch('ceilometer.neutron_client.Client.'
|
||||
'member_get_all',
|
||||
return_value=fake_members))
|
||||
|
||||
@staticmethod
|
||||
def fake_get_members():
|
||||
return [{'status': 'ACTIVE',
|
||||
'protocol_port': 80,
|
||||
'weight': 1,
|
||||
'admin_state_up': True,
|
||||
'tenant_id': 'a4eb9f4938bb418bbc4f8eb31802fefa',
|
||||
'pool_id': 'ce73ad36-437d-4c84-aee1-186027d3da9a',
|
||||
'address': '10.0.0.3',
|
||||
'status_description': None,
|
||||
'id': '290b61eb-07bc-4372-9fbf-36459dd0f96b'},
|
||||
{'status': 'INACTIVE',
|
||||
'protocol_port': 80,
|
||||
'weight': 1,
|
||||
'admin_state_up': True,
|
||||
'tenant_id': 'a4eb9f4938bb418bbc4f8eb31802fefa',
|
||||
'pool_id': 'ce73ad36-437d-4c84-aee1-186027d3da9a',
|
||||
'address': '10.0.0.5',
|
||||
'status_description': None,
|
||||
'id': '2456661eb-07bc-4372-9fbf-36459dd0f96b'},
|
||||
{'status': 'PENDING_CREATE',
|
||||
'protocol_port': 80,
|
||||
'weight': 1,
|
||||
'admin_state_up': True,
|
||||
'tenant_id': 'a4eb9f4938bb418bbc4f8eb31802fefa',
|
||||
'pool_id': 'ce73ad36-437d-4c84-aee1-186027d3da9a',
|
||||
'address': '10.0.0.6',
|
||||
'status_description': None,
|
||||
'id': '45630b61eb-07bc-4372-9fbf-36459dd0f96b'},
|
||||
{'status': 'UNKNOWN',
|
||||
'protocol_port': 80,
|
||||
'weight': 1,
|
||||
'admin_state_up': True,
|
||||
'tenant_id': 'a4eb9f4938bb418bbc4f8eb31802fefa',
|
||||
'pool_id': 'ce73ad36-437d-4c84-aee1-186027d3da9a',
|
||||
'address': '10.0.0.6',
|
||||
'status_description': None,
|
||||
'id': '45630b61eb-07bc-4372-9fbf-36459dd0f96b'},
|
||||
]
|
||||
|
||||
def test_get_samples_not_empty(self):
|
||||
samples = list(self.pollster.get_samples(self.manager, {}))
|
||||
self.assertEqual(3, len(samples))
|
||||
for field in self.pollster.FIELDS:
|
||||
self.assertEqual(self.fake_get_members()[0][field],
|
||||
samples[0].resource_metadata[field])
|
||||
|
||||
def test_pool_volume(self):
|
||||
samples = list(self.pollster.get_samples(self.manager, {}))
|
||||
self.assertEqual(1, samples[0].volume)
|
||||
self.assertEqual(0, samples[1].volume)
|
||||
self.assertEqual(2, samples[2].volume)
|
||||
|
||||
def test_get_meter_names(self):
|
||||
samples = list(self.pollster.get_samples(self.manager, {}))
|
||||
self.assertEqual(set(['network.services.lb.member']),
|
||||
set([s.name for s in samples]))
|
||||
|
||||
|
||||
class TestLBHealthProbePollster(_BaseTestLBPollster):
|
||||
|
||||
def setUp(self):
|
||||
super(TestLBHealthProbePollster, self).setUp()
|
||||
self.pollster = lbaas.LBHealthMonitorPollster()
|
||||
fake_health_monitor = self.fake_get_health_monitor()
|
||||
self.useFixture(mockpatch.Patch('ceilometer.neutron_client.Client.'
|
||||
'health_monitor_get_all',
|
||||
return_value=fake_health_monitor))
|
||||
|
||||
@staticmethod
|
||||
def fake_get_health_monitor():
|
||||
return [{'id': '34ae33e1-0035-49e2-a2ca-77d5d3fab365',
|
||||
'admin_state_up': True,
|
||||
'tenant_id': "d5d2817dae6b42159be9b665b64beb0e",
|
||||
'delay': 2,
|
||||
'max_retries': 5,
|
||||
'timeout': 5,
|
||||
'pools': [],
|
||||
'type': 'PING',
|
||||
}]
|
||||
|
||||
def test_get_samples_not_empty(self):
|
||||
samples = list(self.pollster.get_samples(self.manager, {}))
|
||||
self.assertEqual(1, len(samples))
|
||||
for field in self.pollster.FIELDS:
|
||||
self.assertEqual(self.fake_get_health_monitor()[0][field],
|
||||
samples[0].resource_metadata[field])
|
||||
|
||||
def test_get_meter_names(self):
|
||||
samples = list(self.pollster.get_samples(self.manager, {}))
|
||||
self.assertEqual(set(['network.services.lb.health_monitor']),
|
||||
set([s.name for s in samples]))
|
||||
|
||||
|
||||
class TestLBStatsPollster(_BaseTestLBPollster):
|
||||
|
||||
def setUp(self):
|
||||
super(TestLBStatsPollster, self).setUp()
|
||||
fake_pool_stats = self.fake_pool_stats()
|
||||
self.useFixture(mockpatch.Patch('ceilometer.neutron_client.Client.'
|
||||
'pool_stats',
|
||||
return_value=fake_pool_stats))
|
||||
|
||||
fake_pools = self.fake_get_pools()
|
||||
self.useFixture(mockpatch.Patch('ceilometer.neutron_client.Client.'
|
||||
'pool_get_all',
|
||||
return_value=fake_pools))
|
||||
|
||||
@staticmethod
|
||||
def fake_get_pools():
|
||||
return [{'status': 'ACTIVE',
|
||||
'lb_method': 'ROUND_ROBIN',
|
||||
'protocol': 'HTTP',
|
||||
'description': '',
|
||||
'health_monitors': [],
|
||||
'members': [],
|
||||
'provider': 'haproxy',
|
||||
'status_description': None,
|
||||
'id': 'ce73ad36-437d-4c84-aee1-186027d3da9a',
|
||||
'vip_id': 'cd6a6fee-e2fa-4e6c-b3c2-bfbe395752c1',
|
||||
'name': 'mylb',
|
||||
'admin_state_up': True,
|
||||
'subnet_id': 'bbe3d818-bdcb-4e4b-b47f-5650dc8a9d7a',
|
||||
'tenant_id': 'a4eb9f4938bb418bbc4f8eb31802fefa',
|
||||
'health_monitors_status': []},
|
||||
]
|
||||
|
||||
@staticmethod
|
||||
def fake_pool_stats():
|
||||
return {'stats': {'active_connections': 2L,
|
||||
'bytes_in': 1L,
|
||||
'bytes_out': 3L,
|
||||
'total_connections': 4L
|
||||
}
|
||||
}
|
||||
|
||||
@mock.patch('ceilometer.pipeline.setup_pipeline', mock.MagicMock())
|
||||
def _check_get_samples(self, factory, sample_name, expected_volume):
|
||||
pollster = factory()
|
||||
|
||||
cache = {}
|
||||
samples = list(pollster.get_samples(self.manager, cache))
|
||||
self.assertEqual(1, len(samples))
|
||||
self.assertIsNotNone(samples)
|
||||
self.assertIn('lbstats', cache)
|
||||
self.assertEqual(set([sample_name]), set([s.name for s in samples]))
|
||||
|
||||
match = [s for s in samples if s.name == sample_name]
|
||||
self.assertEqual(1, len(match), 'missing counter %s' % sample_name)
|
||||
self.assertEqual(expected_volume, match[0].volume)
|
||||
self.assertEqual('gauge', match[0].type)
|
||||
|
||||
def test_lb_total_connections(self):
|
||||
self._check_get_samples(lbaas.LBTotalConnectionsPollster,
|
||||
'network.services.lb.total.connections', 4L)
|
||||
|
||||
def test_lb_active_connections(self):
|
||||
self._check_get_samples(lbaas.LBActiveConnectionsPollster,
|
||||
'network.services.lb.active.connections', 2L)
|
||||
|
||||
def test_lb_incoming_bytes(self):
|
||||
self._check_get_samples(lbaas.LBBytesInPollster,
|
||||
'network.services.lb.incoming.bytes', 1L)
|
||||
|
||||
def test_lb_outgoing_bytes(self):
|
||||
self._check_get_samples(lbaas.LBBytesOutPollster,
|
||||
'network.services.lb.outgoing.bytes', 3L)
|
@ -38,7 +38,8 @@ class TestNeutronClient(test.BaseTestCase):
|
||||
'name': '',
|
||||
'network_id': '298a3088-a446-4d5a-bad8-f92ecacd786b',
|
||||
'status': 'ACTIVE',
|
||||
'tenant_id': '89271fa581ab4380bf172f868c3615f9'}]}
|
||||
'tenant_id': '89271fa581ab4380bf172f868c3615f9'},
|
||||
]}
|
||||
|
||||
def test_port_get_all(self):
|
||||
with patch.object(self.nc.client, 'list_ports',
|
||||
@ -62,7 +63,8 @@ class TestNeutronClient(test.BaseTestCase):
|
||||
'shared': False,
|
||||
'status': 'ACTIVE',
|
||||
'subnets': [u'c4b6f5b8-3508-4896-b238-a441f25fb492'],
|
||||
'tenant_id': '62d6f08bbd3a44f6ad6f00ca15cce4e5'}]}
|
||||
'tenant_id': '62d6f08bbd3a44f6ad6f00ca15cce4e5'},
|
||||
]}
|
||||
|
||||
def test_network_get_all(self):
|
||||
with patch.object(self.nc.client, 'list_networks',
|
||||
@ -72,3 +74,122 @@ class TestNeutronClient(test.BaseTestCase):
|
||||
self.assertEqual(1, len(networks))
|
||||
self.assertEqual('298a3088-a446-4d5a-bad8-f92ecacd786b',
|
||||
networks[0]['id'])
|
||||
|
||||
@staticmethod
|
||||
def fake_pool_list():
|
||||
return {'pools': [{'status': 'ACTIVE',
|
||||
'lb_method': 'ROUND_ROBIN',
|
||||
'protocol': 'HTTP',
|
||||
'description': '',
|
||||
'health_monitors': [],
|
||||
'members': [],
|
||||
'status_description': None,
|
||||
'id': 'ce73ad36-437d-4c84-aee1-186027d3da9a',
|
||||
'vip_id': 'cd6a6fee-e2fa-4e6c-b3c2-bfbe395752c1',
|
||||
'name': 'mylb',
|
||||
'admin_state_up': True,
|
||||
'subnet_id': 'bbe3d818-bdcb-4e4b-b47f-5650dc8a9d7a',
|
||||
'tenant_id': 'a4eb9f4938bb418bbc4f8eb31802fefa',
|
||||
'health_monitors_status': []},
|
||||
]}
|
||||
|
||||
def test_pool_list(self):
|
||||
with patch.object(self.nc.client, 'list_pools',
|
||||
side_effect=self.fake_pool_list):
|
||||
pools = self.nc.pool_get_all()
|
||||
|
||||
self.assertEqual(1, len(pools))
|
||||
self.assertEqual('ce73ad36-437d-4c84-aee1-186027d3da9a',
|
||||
pools[0]['id'])
|
||||
|
||||
@staticmethod
|
||||
def fake_vip_list():
|
||||
return {'vips': [{'status': 'ACTIVE',
|
||||
'status_description': None,
|
||||
'protocol': 'HTTP',
|
||||
'description': '',
|
||||
'admin_state_up': True,
|
||||
'subnet_id': 'bbe3d818-bdcb-4e4b-b47f-5650dc8a9d7a',
|
||||
'tenant_id': 'a4eb9f4938bb418bbc4f8eb31802fefa',
|
||||
'connection_limit': -1,
|
||||
'pool_id': 'ce73ad36-437d-4c84-aee1-186027d3da9a',
|
||||
'session_persistence': None,
|
||||
'address': '10.0.0.2',
|
||||
'protocol_port': 80,
|
||||
'port_id': '3df3c4de-b32e-4ca1-a7f4-84323ba5f291',
|
||||
'id': 'cd6a6fee-e2fa-4e6c-b3c2-bfbe395752c1',
|
||||
'name': 'myvip'},
|
||||
]}
|
||||
|
||||
def test_vip_list(self):
|
||||
with patch.object(self.nc.client, 'list_vips',
|
||||
side_effect=self.fake_vip_list):
|
||||
vips = self.nc.vip_get_all()
|
||||
|
||||
self.assertEqual(1, len(vips))
|
||||
self.assertEqual('cd6a6fee-e2fa-4e6c-b3c2-bfbe395752c1',
|
||||
vips[0]['id'])
|
||||
|
||||
@staticmethod
|
||||
def fake_member_list():
|
||||
return {'members': [{'status': 'ACTIVE',
|
||||
'protocol_port': 80,
|
||||
'weight': 1,
|
||||
'admin_state_up': True,
|
||||
'tenant_id': 'a4eb9f4938bb418bbc4f8eb31802fefa',
|
||||
'pool_id': 'ce73ad36-437d-4c84-aee1-186027d3da9a',
|
||||
'address': '10.0.0.3',
|
||||
'status_description': None,
|
||||
'id': '290b61eb-07bc-4372-9fbf-36459dd0f96b'},
|
||||
]}
|
||||
|
||||
def test_member_list(self):
|
||||
with patch.object(self.nc.client, 'list_members',
|
||||
side_effect=self.fake_member_list):
|
||||
members = self.nc.member_get_all()
|
||||
|
||||
self.assertEqual(1, len(members))
|
||||
self.assertEqual('290b61eb-07bc-4372-9fbf-36459dd0f96b',
|
||||
members[0]['id'])
|
||||
|
||||
@staticmethod
|
||||
def fake_monitors_list():
|
||||
return {'health_monitors':
|
||||
[{'id': '34ae33e1-0035-49e2-a2ca-77d5d3fab365',
|
||||
'admin_state_up': True,
|
||||
'tenant_id': "d5d2817dae6b42159be9b665b64beb0e",
|
||||
'delay': 2,
|
||||
'max_retries': 5,
|
||||
'timeout': 5,
|
||||
'pools': [],
|
||||
'type': 'PING',
|
||||
}]}
|
||||
|
||||
def test_monitor_list(self):
|
||||
with patch.object(self.nc.client, 'list_health_monitors',
|
||||
side_effect=self.fake_monitors_list):
|
||||
monitors = self.nc.health_monitor_get_all()
|
||||
|
||||
self.assertEqual(1, len(monitors))
|
||||
self.assertEqual('34ae33e1-0035-49e2-a2ca-77d5d3fab365',
|
||||
monitors[0]['id'])
|
||||
|
||||
@staticmethod
|
||||
def fake_pool_stats(fake_pool):
|
||||
return {'stats':
|
||||
[{'active_connections': 1L,
|
||||
'total_connections': 2L,
|
||||
'bytes_in': 3L,
|
||||
'bytes_out': 4L
|
||||
}]}
|
||||
|
||||
def test_pool_stats(self):
|
||||
with patch.object(self.nc.client, 'retrieve_pool_stats',
|
||||
side_effect=self.fake_pool_stats):
|
||||
stats = self.nc.pool_stats('fake_pool')['stats']
|
||||
|
||||
self.assertEqual(1, len(stats))
|
||||
self.assertEqual(1L, stats[0]['active_connections'])
|
||||
self.assertEqual(2L, stats[0]['total_connections'])
|
||||
self.assertEqual(3L, stats[0]['bytes_in'])
|
||||
self.assertEqual(4L, stats[0]['bytes_out'])
|
||||
|
@ -135,7 +135,14 @@ ceilometer.poll.central =
|
||||
hardware.network.outgoing.errors = ceilometer.hardware.pollsters.net:OutgoingErrorsPollster
|
||||
hardware.memory.total = ceilometer.hardware.pollsters.memory:MemoryTotalPollster
|
||||
hardware.memory.used = ceilometer.hardware.pollsters.memory:MemoryUsedPollster
|
||||
|
||||
network.services.lb.pool = ceilometer.network.services.lbaas:LBPoolPollster
|
||||
network.services.lb.vip = ceilometer.network.services.lbaas:LBVipPollster
|
||||
network.services.lb.member = ceilometer.network.services.lbaas:LBMemberPollster
|
||||
network.services.lb.health_monitor = ceilometer.network.services.lbaas:LBHealthMonitorPollster
|
||||
network.services.lb.total.connections = ceilometer.network.services.lbaas:LBTotalConnectionsPollster
|
||||
network.services.lb.active.connections = ceilometer.network.services.lbaas:LBActiveConnectionsPollster
|
||||
network.services.lb.incoming.bytes = ceilometer.network.services.lbaas:LBBytesInPollster
|
||||
network.services.lb.outgoing.bytes = ceilometer.network.services.lbaas:LBBytesOutPollster
|
||||
|
||||
ceilometer.storage =
|
||||
log = ceilometer.storage.impl_log:Connection
|
||||
|
Loading…
Reference in New Issue
Block a user