#
# 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
from oslo.utils import timeutils
import six
from ceilometer.network.services import base
from ceilometer.openstack.common.gettextutils import _
from ceilometer.openstack.common import log
from ceilometer import sample
LOG = log.getLogger(__name__)
LBStatsData = collections.namedtuple(
'LBStats',
['active_connections', 'total_connections', 'bytes_in', 'bytes_out']
)
[docs]class LBPoolPollster(base.BaseServicesPollster):
"""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'
]
@property
def default_discovery(self):
return 'lb_pools'
[docs] def get_samples(self, manager, cache, resources):
resources = resources or []
for pool in resources:
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 %(stat)s received on pool %(id)s, "
"skipping sample") % {'stat': pool['status'],
'id': 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)
)
[docs]class LBVipPollster(base.BaseServicesPollster):
"""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',
]
@property
def default_discovery(self):
return 'lb_vips'
[docs] def get_samples(self, manager, cache, resources):
resources = resources or []
for vip in resources:
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 %(stat)s received on vip %(id)s, "
"skipping sample") % {'stat': vip['status'],
'id': 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)
)
[docs]class LBMemberPollster(base.BaseServicesPollster):
"""Pollster to capture Load Balancer Member status samples."""
FIELDS = ['admin_state_up',
'address',
'pool_id',
'protocol_port',
'status',
'status_description',
'weight',
]
@property
def default_discovery(self):
return 'lb_members'
[docs] def get_samples(self, manager, cache, resources):
resources = resources or []
for member in resources:
LOG.debug("Load Balancer Member : %s" % member)
status = self.get_status_id(member['status'])
if status == -1:
LOG.warn(_("Unknown status %(stat)s received on member %(id)s,"
"skipping sample") % {'stat': member['status'],
'id': 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)
)
[docs]class LBHealthMonitorPollster(base.BaseServicesPollster):
"""Pollster to capture Load Balancer Health probes status samples."""
FIELDS = ['admin_state_up',
'delay',
'max_retries',
'pools',
'timeout',
'type'
]
@property
def default_discovery(self):
return 'lb_health_probes'
[docs] def get_samples(self, manager, cache, resources):
for probe in resources:
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(base.BaseServicesPollster):
"""Base Statistics pollster.
It is 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]
@property
def default_discovery(self):
return 'lb_pools'
@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})
[docs]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,
)
[docs]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,
)
[docs]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_CUMULATIVE,
unit='B',
volume=data.bytes_in,
)
[docs]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_CUMULATIVE,
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,
)