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:
Pradeep Kilambi 2014-05-23 11:13:04 -07:00
parent a30beaacfa
commit 3add1f7832
7 changed files with 900 additions and 3 deletions

View File

View 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,
)

View File

@ -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)

View 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)

View File

@ -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'])

View File

@ -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