Commit e7a3d62f authored by Zi Lian Ji's avatar Zi Lian Ji

Enable the Load Balancer v2 for the Ceilometer(Part Two)

In this change set, add the new methods to collect the new meters
in the LBaaS v2[1].

list_listener: list all the listeners
list_loadbalancer: list all the loadbalancers
get_loadbalancer_stats : get the statistics of the specified
loadbalancer.

[1]https://wiki.openstack.org/wiki/Neutron/LBaaS/API_2.0Co-Authored-By: default avatarXia Linjuan <ljxiash@cn.ibm.com>
DocImpact: new metrics are introduced
Change-Id: I982f28917d1f8fd3d4352037f8832de9ef869942
Implements: blueprint lbaas-v2-enablement
parent 95b2615d
......@@ -52,6 +52,24 @@ class LBMembersDiscovery(_BaseServicesDiscovery):
if i.get('status', None) != 'error']
class LBListenersDiscovery(_BaseServicesDiscovery):
def discover(self, manager, param=None):
"""Discover load balancer listener resources to monitor."""
listeners = self.neutron_cli.list_listener()
return [i for i in listeners
if i.get('operating_status', None) != 'error']
class LBLoadBalancersDiscovery(_BaseServicesDiscovery):
def discover(self, manager, param=None):
"""Discover load balancer resources to monitor."""
loadbalancers = self.neutron_cli.list_loadbalancer()
return [i for i in loadbalancers
if i.get('operating_status', None) != 'error']
class LBHealthMonitorsDiscovery(_BaseServicesDiscovery):
def discover(self, manager, param=None):
"""Discover resources to monitor."""
......
......@@ -233,6 +233,7 @@ class _LBStatsPollster(base.BaseServicesPollster):
def __init__(self):
super(_LBStatsPollster, self).__init__()
self.client = neutron_client.Client()
self.lb_version = cfg.CONF.service_types.neutron_lbaas_version
@staticmethod
def make_sample_from_pool(pool, name, type, unit, volume,
......@@ -263,22 +264,49 @@ class _LBStatsPollster(base.BaseServicesPollster):
)
return i_cache[pool_id]
def _populate_stats_cache_v2(self, loadbalancer_id, cache):
i_cache = cache.setdefault("lbstats", {})
if loadbalancer_id not in i_cache:
stats = self.client.get_loadbalancer_stats(loadbalancer_id)
i_cache[loadbalancer_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[loadbalancer_id]
@property
def default_discovery(self):
return 'lb_pools'
discovery_resource = 'lb_pools'
if self.lb_version == 'v2':
discovery_resource = 'lb_loadbalancers'
return discovery_resource
@abc.abstractmethod
def _get_sample(pool, c_data):
"""Return one Sample."""
def get_samples(self, manager, cache, resources):
for pool in resources:
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})
if self.lb_version == 'v1':
for pool in resources:
try:
c_data = self._populate_stats_cache(pool['id'], cache)
yield self._get_sample(pool, c_data)
except Exception:
LOG.exception(_('Ignoring pool %(pool_id)s'),
{'pool_id': pool['id']})
elif self.lb_version == 'v2':
for loadbalancer in resources:
try:
c_data = self._populate_stats_cache_v2(loadbalancer['id'],
cache)
yield self._get_sample(loadbalancer, c_data)
except Exception:
LOG.exception(
_('Ignoring '
'loadbalancer %(loadbalancer_id)s'),
{'loadbalancer_id': loadbalancer['id']})
class LBActiveConnectionsPollster(_LBStatsPollster):
......@@ -352,3 +380,94 @@ def make_sample_from_pool(pool, name, type, unit, volume,
timestamp=timeutils.utcnow().isoformat(),
resource_metadata=resource_metadata,
)
class LBListenerPollster(BaseLBPollster):
"""Pollster to capture Load Balancer Listener status samples."""
FIELDS = ['admin_state_up',
'connection_limit',
'description',
'name',
'default_pool_id',
'protocol',
'protocol_port',
'operating_status',
'loadbalancers'
]
@property
def default_discovery(self):
return 'lb_listeners'
def get_samples(self, manager, cache, resources):
resources = resources or []
for listener in resources:
LOG.debug("Load Balancer Listener : %s" % listener)
status = self.get_load_balancer_status_id(
listener['operating_status'])
if status == -1:
# unknown status, skip this sample
LOG.warning(_("Unknown status %(stat)s received on listener "
"%(id)s, skipping sample")
% {'stat': listener['operating_status'],
'id': listener['id']})
continue
yield sample.Sample(
name='network.services.lb.listener',
type=sample.TYPE_GAUGE,
unit='listener',
volume=status,
user_id=None,
project_id=listener['tenant_id'],
resource_id=listener['id'],
timestamp=timeutils.utcnow().isoformat(),
resource_metadata=self.extract_metadata(listener)
)
class LBLoadBalancerPollster(BaseLBPollster):
"""Pollster to capture Load Balancer status samples."""
FIELDS = ['admin_state_up',
'description',
'vip_address',
'listeners',
'name',
'vip_subnet_id',
'operating_status',
]
@property
def default_discovery(self):
return 'lb_loadbalancers'
def get_samples(self, manager, cache, resources):
resources = resources or []
for loadbalancer in resources:
LOG.debug("Load Balancer: %s" % loadbalancer)
status = self.get_load_balancer_status_id(
loadbalancer['operating_status'])
if status == -1:
# unknown status, skip this sample
LOG.warning(_("Unknown status %(stat)s received "
"on Load Balancer "
"%(id)s, skipping sample")
% {'stat': loadbalancer['operating_status'],
'id': loadbalancer['id']})
continue
yield sample.Sample(
name='network.services.lb.loadbalancer',
type=sample.TYPE_GAUGE,
unit='loadbalancer',
volume=status,
user_id=None,
project_id=loadbalancer['tenant_id'],
resource_id=loadbalancer['id'],
timestamp=timeutils.utcnow().isoformat(),
resource_metadata=self.extract_metadata(loadbalancer)
)
......@@ -385,3 +385,28 @@ class Client(object):
break
return status_dict
def list_listener(self):
"""This method is used to get the list of the listeners."""
resp = self.client.list_listeners()
resources = resp.get('listeners')
for listener in resources:
loadbalancer_id = listener.get('loadbalancers')[0].get('id')
status = self._get_listener_status(loadbalancer_id)
listener['operating_status'] = status[listener.get('id')]
return resources
def list_loadbalancer(self):
"""This method is used to get the list of the loadbalancers."""
resp = self.client.list_loadbalancers()
resources = resp.get('loadbalancers')
return resources
def get_loadbalancer_stats(self, loadbalancer_id):
"""This method is used to get the statistics of the loadbalancer.
:param loadbalancer_id: the ID of the specified loadbalancer
"""
resp = self.client.retrieve_loadbalancer_stats(loadbalancer_id)
resource = resp.get('stats')
return resource
......@@ -474,7 +474,6 @@ class TestLBStatsPollster(_BaseTestLBPollster):
def _check_get_samples(self, factory, sample_name, expected_volume,
expected_type):
pollster = factory()
cache = {}
samples = list(pollster.get_samples(self.manager, cache,
self.fake_get_pools()))
......
This diff is collapsed.
......@@ -197,6 +197,24 @@ class TestNeutronClientLBaaSV2(base.BaseTestCase):
}
}
@staticmethod
def fake_list_lbaas_listeners():
return {
'listeners': [{
'default_pool_id': None,
'protocol': 'HTTP',
'description': '',
'admin_state_up': True,
'loadbalancers': [{
'id': 'a9729389-6147-41a3-ab22-a24aed8692b2'
}],
'tenant_id': '3e4d8bec50a845fcb09e03a4375c691d',
'connection_limit': 100,
'protocol_port': 80,
'id': '35cb8516-1173-4035-8dae-0dae3453f37f',
'name': 'listener_one'
}]}
@mock.patch.object(client.Client,
'list_lbaas_pools')
@mock.patch.object(client.Client,
......@@ -300,3 +318,19 @@ class TestNeutronClientLBaaSV2(base.BaseTestCase):
for key in result_status.keys():
self.assertIn(key, expected_keys)
self.assertEqual(excepted_status[key], result_status[key])
@mock.patch.object(client.Client,
'list_listeners')
@mock.patch.object(neutron_client.Client,
'_retrieve_loadbalancer_status_tree')
def test_list_listener(self, mock_status, mock_list_listeners):
mock_list_listeners.return_value = (
self.fake_list_lbaas_listeners())
mock_status.return_value = (
self.fake_retrieve_loadbalancer_status())
listeners = self.nc.list_listener()
expected_key = '35cb8516-1173-4035-8dae-0dae3453f37f'
expected_status = 'ONLINE'
self.assertEqual(1, len(listeners))
self.assertEqual(expected_key, listeners[0]['id'])
self.assertEqual(expected_status, listeners[0]['operating_status'])
......@@ -64,6 +64,8 @@ ceilometer.discover =
lb_pools = ceilometer.network.services.discovery:LBPoolsDiscovery
lb_vips = ceilometer.network.services.discovery:LBVipsDiscovery
lb_members = ceilometer.network.services.discovery:LBMembersDiscovery
lb_listeners = ceilometer.network.services.discovery:LBListenersDiscovery
lb_loadbalancers = ceilometer.network.services.discovery:LBLoadBalancersDiscovery
lb_health_probes = ceilometer.network.services.discovery:LBHealthMonitorsDiscovery
vpn_services = ceilometer.network.services.discovery:VPNServicesDiscovery
ipsec_connections = ceilometer.network.services.discovery:IPSecConnectionsDiscovery
......@@ -167,6 +169,8 @@ ceilometer.poll.central =
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.listener = ceilometer.network.services.lbaas:LBListenerPollster
network.services.lb.loadbalancer = ceilometer.network.services.lbaas:LBLoadBalancerPollster
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
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment