Create OpenStackClients convenience class
The OpenStackClients class provides a convenient way to create and cache client instances. The idea behind this code comes from Magnum [0]. The OpenStackClients class will act as the manager of other project's clients, providing an easy way to fetch instances of said clients. This will allow the clients to be cached. An instance of OpenStackClients is created for every call that comes into the decision engine and the applier, using the request context to pass needed (domain id) parameters to get a Keystone session. This instance should be shared as much as possible to avoid additional unneccessary connections to the other services. This class will also allow for the version of each client to be configurable via the watcher.conf file. The method by which a Keystone session is also changed to use the keystoneauth1.loading library. In order to avoid DuplicateOptErrors with the keystone_authtoken group used for the keystonemiddleware in the API code, a new conf group named "watcher_clients_auth" is created. A typical configuration using a password authentication scheme will look like: [watcher_clients_auth] auth_type = password auth_url = http://<server-ip>:<port> username = <username> password = <password> project_domain_id = default user_domain_id = default [0]: https://github.com/openstack/magnum/blob/master/magnum/common/clients.py DocImpact Change-Id: Iab9d0b304099686da2e9e2b19e8b1de4332ff378 Implements: blueprint external-api-versioning Closes-Bug: #1530790 Closes-Bug: #1539670 Closes-Bug: #1522774
This commit is contained in:
146
watcher/common/ceilometer_helper.py
Normal file
146
watcher/common/ceilometer_helper.py
Normal file
@@ -0,0 +1,146 @@
|
||||
# -*- encoding: utf-8 -*-
|
||||
# Copyright (c) 2015 b<>com
|
||||
#
|
||||
# Authors: Jean-Emile DARTOIS <jean-emile.dartois@b-com.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.
|
||||
#
|
||||
|
||||
from ceilometerclient.exc import HTTPUnauthorized
|
||||
|
||||
from watcher.common import clients
|
||||
|
||||
|
||||
class CeilometerHelper(object):
|
||||
def __init__(self, osc=None):
|
||||
""":param osc: an OpenStackClients instance"""
|
||||
self.osc = osc if osc else clients.OpenStackClients()
|
||||
self.ceilometer = self.osc.ceilometer()
|
||||
|
||||
def build_query(self, user_id=None, tenant_id=None, resource_id=None,
|
||||
user_ids=None, tenant_ids=None, resource_ids=None):
|
||||
"""Returns query built from given parameters.
|
||||
|
||||
This query can be then used for querying resources, meters and
|
||||
statistics.
|
||||
:Parameters:
|
||||
- `user_id`: user_id, has a priority over list of ids
|
||||
- `tenant_id`: tenant_id, has a priority over list of ids
|
||||
- `resource_id`: resource_id, has a priority over list of ids
|
||||
- `user_ids`: list of user_ids
|
||||
- `tenant_ids`: list of tenant_ids
|
||||
- `resource_ids`: list of resource_ids
|
||||
"""
|
||||
|
||||
user_ids = user_ids or []
|
||||
tenant_ids = tenant_ids or []
|
||||
resource_ids = resource_ids or []
|
||||
|
||||
query = []
|
||||
if user_id:
|
||||
user_ids = [user_id]
|
||||
for u_id in user_ids:
|
||||
query.append({"field": "user_id", "op": "eq", "value": u_id})
|
||||
|
||||
if tenant_id:
|
||||
tenant_ids = [tenant_id]
|
||||
for t_id in tenant_ids:
|
||||
query.append({"field": "project_id", "op": "eq", "value": t_id})
|
||||
|
||||
if resource_id:
|
||||
resource_ids = [resource_id]
|
||||
for r_id in resource_ids:
|
||||
query.append({"field": "resource_id", "op": "eq", "value": r_id})
|
||||
|
||||
return query
|
||||
|
||||
def query_retry(self, f, *args, **kargs):
|
||||
try:
|
||||
return f(*args, **kargs)
|
||||
except HTTPUnauthorized:
|
||||
self.osc.reset_clients()
|
||||
self.ceilometer = self.osc.ceilometer()
|
||||
return f(*args, **kargs)
|
||||
except Exception:
|
||||
raise
|
||||
|
||||
def query_sample(self, meter_name, query, limit=1):
|
||||
return self.query_retry(f=self.ceilometer.samples.list,
|
||||
meter_name=meter_name,
|
||||
limit=limit,
|
||||
q=query)
|
||||
|
||||
def statistic_list(self, meter_name, query=None, period=None):
|
||||
"""List of statistics."""
|
||||
statistics = self.ceilometer.statistics.list(
|
||||
meter_name=meter_name,
|
||||
q=query,
|
||||
period=period)
|
||||
return statistics
|
||||
|
||||
def meter_list(self, query=None):
|
||||
"""List the user's meters."""
|
||||
meters = self.query_retry(f=self.ceilometer.meters.list,
|
||||
query=query)
|
||||
return meters
|
||||
|
||||
def statistic_aggregation(self,
|
||||
resource_id,
|
||||
meter_name,
|
||||
period,
|
||||
aggregate='avg'):
|
||||
"""Representing a statistic aggregate by operators
|
||||
|
||||
:param resource_id: id
|
||||
:param meter_name: meter names of which we want the statistics
|
||||
:param period: `period`: In seconds. If no period is given, only one
|
||||
aggregate statistic is returned. If given, a faceted
|
||||
result will be returned, divided into given periods.
|
||||
Periods with no data are ignored.
|
||||
:param aggregate:
|
||||
:return:
|
||||
"""
|
||||
|
||||
query = self.build_query(resource_id=resource_id)
|
||||
statistic = self.query_retry(f=self.ceilometer.statistics.list,
|
||||
meter_name=meter_name,
|
||||
q=query,
|
||||
period=period,
|
||||
aggregates=[
|
||||
{'func': aggregate}],
|
||||
groupby=['resource_id'])
|
||||
|
||||
item_value = None
|
||||
if statistic:
|
||||
item_value = statistic[-1]._info.get('aggregate').get('avg')
|
||||
return item_value
|
||||
|
||||
def get_last_sample_values(self, resource_id, meter_name, limit=1):
|
||||
samples = self.query_sample(meter_name=meter_name,
|
||||
query=self.build_query(resource_id))
|
||||
values = []
|
||||
for index, sample in enumerate(samples):
|
||||
values.append(
|
||||
{'sample_%s' % index: {'timestamp': sample._info['timestamp'],
|
||||
'value': sample._info[
|
||||
'counter_volume']}})
|
||||
return values
|
||||
|
||||
def get_last_sample_value(self, resource_id, meter_name):
|
||||
samples = self.query_sample(meter_name=meter_name,
|
||||
query=self.build_query(resource_id))
|
||||
if samples:
|
||||
return samples[-1]._info['counter_volume']
|
||||
else:
|
||||
return False
|
||||
Reference in New Issue
Block a user