Drop deprecated api v1

API v1 is deprecated since havana,
so remove it now.

Change-Id: If147d018ee571087eb3c11be6e1e66d9ab66cb22
This commit is contained in:
Mehdi Abaakouk 2014-05-16 00:59:42 +02:00
parent d646d8400d
commit 6a7d6ec198
41 changed files with 9 additions and 31334 deletions

View File

@ -35,9 +35,6 @@ from ceilometer import storage
LOG = log.getLogger(__name__)
auth_opts = [
cfg.BoolOpt('enable_v1_api',
default=True,
help='Deploy the deprecated v1 API.'),
cfg.StrOpt('api_paste_config',
default="api_paste.ini",
help="Configuration file for WSGI definition of API."
@ -88,14 +85,12 @@ class VersionSelectorApplication(object):
def __init__(self):
pc = get_pecan_config()
pc.app.debug = CONF.debug
if cfg.CONF.enable_v1_api:
from ceilometer.api.v1 import app as v1app
self.v1 = v1app.make_app(cfg.CONF)
else:
def not_found(environ, start_response):
start_response('404 Not Found', [])
return []
self.v1 = not_found
def not_found(environ, start_response):
start_response('404 Not Found', [])
return []
self.v1 = not_found
self.v2 = setup_app(pecan_config=pc)
def __call__(self, environ, start_response):

View File

@ -1,61 +0,0 @@
# -*- encoding: utf-8 -*-
#
# Copyright © 2012 New Dream Network, LLC (DreamHost)
#
# Author: Doug Hellmann <doug.hellmann@dreamhost.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.
"""Set up the API server application instance."""
import flask
from oslo.config import cfg
from ceilometer.api.v1 import blueprint as v1_blueprint
from ceilometer.openstack.common import jsonutils
from ceilometer import storage
class JSONEncoder(flask.json.JSONEncoder):
@staticmethod
def default(o):
return jsonutils.to_primitive(o)
def make_app(conf, attach_storage=True,
sources_file='sources.json'):
app = flask.Flask('ceilometer.api')
app.register_blueprint(v1_blueprint.blueprint, url_prefix='/v1')
app.json_encoder = JSONEncoder
try:
with open(sources_file, "r") as f:
sources = jsonutils.load(f)
except IOError:
sources = {}
@app.before_request
def attach_config():
flask.request.cfg = conf
flask.request.sources = sources
if attach_storage:
@app.before_request
def attach_storage():
flask.request.storage_conn = \
storage.get_connection_from_config(conf)
return app
# For documentation
app = make_app(cfg.CONF, attach_storage=False)

View File

@ -1,703 +0,0 @@
# -*- encoding: utf-8 -*-
#
# Copyright © 2012 New Dream Network, LLC (DreamHost)
#
# Author: Doug Hellmann <doug.hellmann@dreamhost.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.
"""Blueprint for version 1 of API.
"""
#############################################################################
#############################################################################
#
# NOTE(dhellmann): The V1 API is being deprecated during Havana, and
# as such it is feature-frozen. Only make bug-fix changes in this file.
#
#############################################################################
#############################################################################
# [ ] / -- information about this version of the API
#
# [ ] /extensions -- list of available extensions
# [ ] /extensions/<extension> -- details about a specific extension
#
# [ ] /sources -- list of known sources (where do we get this?)
# [ ] /sources/components -- list of components which provide metering
# data (where do we get this)?
#
# [x] /projects/<project>/resources -- list of resource ids
# [x] /resources -- list of resource ids
# [x] /sources/<source>/resources -- list of resource ids
# [x] /users/<user>/resources -- list of resource ids
#
# [x] /users -- list of user ids
# [x] /sources/<source>/users -- list of user ids
#
# [x] /projects -- list of project ids
# [x] /sources/<source>/projects -- list of project ids
#
# [ ] /resources/<resource> -- metadata
#
# [x] /meters -- list of meters
# [x] /projects/<project>/meters -- list of meters reporting for parent obj
# [x] /resources/<resource>/meters -- list of meters reporting for parent obj
# [x] /sources/<source>/meters -- list of meters reporting for parent obj
# [x] /users/<user>/meters -- list of meters reporting for parent obj
#
# [x] /projects/<project>/meters/<meter> -- samples
# [x] /resources/<resource>/meters/<meter> -- samples
# [x] /sources/<source>/meters/<meter> -- samples
# [x] /users/<user>/meters/<meter> -- samples
#
# [ ] /projects/<project>/meters/<meter>/duration -- total time for selected
# meter
# [x] /resources/<resource>/meters/<meter>/duration -- total time for selected
# meter
# [ ] /sources/<source>/meters/<meter>/duration -- total time for selected
# meter
# [ ] /users/<user>/meters/<meter>/duration -- total time for selected meter
#
# [ ] /projects/<project>/meters/<meter>/volume -- total or max volume for
# selected meter
# [x] /projects/<project>/meters/<meter>/volume/max -- max volume for
# selected meter
# [x] /projects/<project>/meters/<meter>/volume/sum -- total volume for
# selected meter
# [ ] /resources/<resource>/meters/<meter>/volume -- total or max volume for
# selected meter
# [x] /resources/<resource>/meters/<meter>/volume/max -- max volume for
# selected meter
# [x] /resources/<resource>/meters/<meter>/volume/sum -- total volume for
# selected meter
# [ ] /sources/<source>/meters/<meter>/volume -- total or max volume for
# selected meter
# [ ] /users/<user>/meters/<meter>/volume -- total or max volume for selected
# meter
import datetime
import flask
from ceilometer.openstack.common.gettextutils import _
from ceilometer.openstack.common import log
from ceilometer.openstack.common import timeutils
from ceilometer import storage
from ceilometer.api import acl
LOG = log.getLogger(__name__)
blueprint = flask.Blueprint('v1', __name__,
template_folder='templates',
static_folder='static')
def request_wants_html():
best = flask.request.accept_mimetypes \
.best_match(['application/json', 'text/html'])
return best == 'text/html' and \
flask.request.accept_mimetypes[best] > \
flask.request.accept_mimetypes['application/json']
def _get_metaquery(args):
return dict((k, v)
for (k, v) in args.iteritems()
if k.startswith('metadata.'))
def check_authorized_project(project):
authorized_project = acl.get_limited_to_project(flask.request.headers)
if authorized_project and authorized_project != project:
flask.abort(404)
## APIs for working with meters.
@blueprint.route('/meters')
def list_meters_all():
"""Return a list of meters.
:param metadata.<key>: match on the metadata within the resource.
(optional)
"""
rq = flask.request
meters = rq.storage_conn.get_meters(
project=acl.get_limited_to_project(rq.headers),
metaquery=_get_metaquery(rq.args))
return flask.jsonify(meters=[m.as_dict() for m in meters])
@blueprint.route('/resources/<resource>/meters')
def list_meters_by_resource(resource):
"""Return a list of meters by resource.
:param resource: The ID of the resource.
:param metadata.<key>: match on the metadata within the resource.
(optional)
"""
rq = flask.request
meters = rq.storage_conn.get_meters(
resource=resource,
project=acl.get_limited_to_project(rq.headers),
metaquery=_get_metaquery(rq.args))
return flask.jsonify(meters=[m.as_dict() for m in meters])
@blueprint.route('/users/<user>/meters')
def list_meters_by_user(user):
"""Return a list of meters by user.
:param user: The ID of the owning user.
:param metadata.<key>: match on the metadata within the resource.
(optional)
"""
rq = flask.request
meters = rq.storage_conn.get_meters(
user=user,
project=acl.get_limited_to_project(rq.headers),
metaquery=_get_metaquery(rq.args))
return flask.jsonify(meters=[m.as_dict() for m in meters])
@blueprint.route('/projects/<project>/meters')
def list_meters_by_project(project):
"""Return a list of meters by project.
:param project: The ID of the owning project.
:param metadata.<key>: match on the metadata within the resource.
(optional)
"""
check_authorized_project(project)
rq = flask.request
meters = rq.storage_conn.get_meters(
project=project,
metaquery=_get_metaquery(rq.args))
return flask.jsonify(meters=[m.as_dict() for m in meters])
@blueprint.route('/sources/<source>/meters')
def list_meters_by_source(source):
"""Return a list of meters by source.
:param source: The ID of the owning source.
:param metadata.<key>: match on the metadata within the resource.
(optional)
"""
rq = flask.request
meters = rq.storage_conn.get_meters(
source=source,
project=acl.get_limited_to_project(rq.headers),
metaquery=_get_metaquery(rq.args))
return flask.jsonify(meters=[m.as_dict() for m in meters])
## APIs for working with resources.
def _list_resources(source=None, user=None, project=None):
"""Return a list of resource identifiers.
"""
rq = flask.request
q_ts = _get_query_timestamps(rq.args)
resources = rq.storage_conn.get_resources(
source=source,
user=user,
project=project,
start_timestamp=q_ts['start_timestamp'],
end_timestamp=q_ts['end_timestamp'],
metaquery=_get_metaquery(rq.args),
)
return flask.jsonify(resources=[r.as_dict() for r in resources])
@blueprint.route('/projects/<project>/resources')
def list_resources_by_project(project):
"""Return a list of resources owned by the project.
:param project: The ID of the owning project.
:param start_timestamp: Limits resources by last update time >= this value.
(optional)
:type start_timestamp: ISO date in UTC
:param end_timestamp: Limits resources by last update time < this value.
(optional)
:type end_timestamp: ISO date in UTC
:param metadata.<key>: match on the metadata within the resource.
(optional)
"""
check_authorized_project(project)
return _list_resources(project=project)
@blueprint.route('/resources')
def list_all_resources():
"""Return a list of all known resources.
:param start_timestamp: Limits resources by last update time >= this value.
(optional)
:type start_timestamp: ISO date in UTC
:param end_timestamp: Limits resources by last update time < this value.
(optional)
:type end_timestamp: ISO date in UTC
:param metadata.<key>: match on the metadata within the resource.
(optional)
"""
return _list_resources(
project=acl.get_limited_to_project(flask.request.headers))
@blueprint.route('/sources/<source>')
def get_source(source):
"""Return a source details.
:param source: The ID of the reporting source.
"""
return flask.jsonify(flask.request.sources.get(source, {}))
@blueprint.route('/sources/<source>/resources')
def list_resources_by_source(source):
"""Return a list of resources for which a source is reporting
data.
:param source: The ID of the reporting source.
:param start_timestamp: Limits resources by last update time >= this value.
(optional)
:type start_timestamp: ISO date in UTC
:param end_timestamp: Limits resources by last update time < this value.
(optional)
:type end_timestamp: ISO date in UTC
:param metadata.<key>: match on the metadata within the resource.
(optional)
"""
return _list_resources(
source=source,
project=acl.get_limited_to_project(flask.request.headers),
)
@blueprint.route('/users/<user>/resources')
def list_resources_by_user(user):
"""Return a list of resources owned by the user.
:param user: The ID of the owning user.
:param start_timestamp: Limits resources by last update time >= this value.
(optional)
:type start_timestamp: ISO date in UTC
:param end_timestamp: Limits resources by last update time < this value.
(optional)
:type end_timestamp: ISO date in UTC
:param metadata.<key>: match on the metadata within the resource.
(optional)
"""
return _list_resources(
user=user,
project=acl.get_limited_to_project(flask.request.headers),
)
## APIs for working with users.
def _list_users(source=None):
"""Return a list of user names.
"""
# TODO(jd) it might be better to return the real list of users that are
# belonging to the project, but that's not provided by the storage
# drivers for now
if acl.get_limited_to_project(flask.request.headers):
users = [flask.request.headers.get('X-User-id')]
else:
users = flask.request.storage_conn.get_users(source=source)
return flask.jsonify(users=list(users))
@blueprint.route('/users')
def list_all_users():
"""Return a list of all known user names.
"""
return _list_users()
@blueprint.route('/sources/<source>/users')
def list_users_by_source(source):
"""Return a list of the users for which the source is reporting
data.
:param source: The ID of the source.
"""
return _list_users(source=source)
## APIs for working with projects.
def _list_projects(source=None):
"""Return a list of project names.
"""
project = acl.get_limited_to_project(flask.request.headers)
if project:
if source:
if project in flask.request.storage_conn.get_projects(
source=source):
projects = [project]
else:
projects = []
else:
projects = [project]
else:
projects = flask.request.storage_conn.get_projects(source=source)
return flask.jsonify(projects=list(projects))
@blueprint.route('/projects')
def list_all_projects():
"""Return a list of all known project names.
"""
return _list_projects()
@blueprint.route('/sources/<source>/projects')
def list_projects_by_source(source):
"""Return a list project names for which the source is reporting
data.
:param source: The ID of the source.
"""
return _list_projects(source=source)
## APIs for working with samples.
def _list_samples(meter,
project=None,
resource=None,
source=None,
user=None):
"""Return a list of raw samples.
Note: the API talks about "events" these are equivalent to samples.
but we still need to return the samples within the "events" dict
to maintain API compatibilty.
"""
q_ts = _get_query_timestamps(flask.request.args)
f = storage.SampleFilter(
user=user,
project=project,
source=source,
meter=meter,
resource=resource,
start=q_ts['start_timestamp'],
end=q_ts['end_timestamp'],
metaquery=_get_metaquery(flask.request.args),
)
samples = flask.request.storage_conn.get_samples(f)
jsonified = flask.jsonify(events=[s.as_dict() for s in samples])
if request_wants_html():
return flask.templating.render_template('list_event.html',
user=user,
project=project,
source=source,
meter=meter,
resource=resource,
events=jsonified)
return jsonified
@blueprint.route('/projects/<project>/meters/<meter>')
def list_samples_by_project(project, meter):
"""Return a list of raw samples for the project.
:param project: The ID of the project.
:param meter: The name of the meter.
:param start_timestamp: Limits samples by timestamp >= this value.
(optional)
:type start_timestamp: ISO date in UTC
:param end_timestamp: Limits samples by timestamp < this value.
(optional)
:type end_timestamp: ISO date in UTC
"""
check_authorized_project(project)
return _list_samples(project=project,
meter=meter,
)
@blueprint.route('/resources/<resource>/meters/<meter>')
def list_samples_by_resource(resource, meter):
"""Return a list of raw samples for the resource.
:param resource: The ID of the resource.
:param meter: The name of the meter.
:param start_timestamp: Limits samples by timestamp >= this value.
(optional)
:type start_timestamp: ISO date in UTC
:param end_timestamp: Limits samples by timestamp < this value.
(optional)
:type end_timestamp: ISO date in UTC
"""
return _list_samples(
resource=resource,
meter=meter,
project=acl.get_limited_to_project(flask.request.headers),
)
@blueprint.route('/sources/<source>/meters/<meter>')
def list_samples_by_source(source, meter):
"""Return a list of raw samples for the source.
:param source: The ID of the reporting source.
:param meter: The name of the meter.
:param start_timestamp: Limits samples by timestamp >= this value.
(optional)
:type start_timestamp: ISO date in UTC
:param end_timestamp: Limits samples by timestamp < this value.
(optional)
:type end_timestamp: ISO date in UTC
"""
return _list_samples(
source=source,
meter=meter,
project=acl.get_limited_to_project(flask.request.headers),
)
@blueprint.route('/users/<user>/meters/<meter>')
def list_samples_by_user(user, meter):
"""Return a list of raw samples for the user.
:param user: The ID of the user.
:param meter: The name of the meter.
:param start_timestamp: Limits samples by timestamp >= this value.
(optional)
:type start_timestamp: ISO date in UTC
:param end_timestamp: Limits samples by timestamp < this value.
(optional)
:type end_timestamp: ISO date in UTC
"""
return _list_samples(
user=user,
meter=meter,
project=acl.get_limited_to_project(flask.request.headers),
)
## APIs for working with meter calculations.
def _get_query_timestamps(args={}):
# Determine the desired range, if any, from the
# GET arguments. Set up the query range using
# the specified offset.
# [query_start ... start_timestamp ... end_timestamp ... query_end]
search_offset = int(args.get('search_offset', 0))
start_timestamp = args.get('start_timestamp')
if start_timestamp:
start_timestamp = timeutils.parse_isotime(start_timestamp)
start_timestamp = start_timestamp.replace(tzinfo=None)
query_start = (start_timestamp -
datetime.timedelta(minutes=search_offset))
else:
query_start = None
end_timestamp = args.get('end_timestamp')
if end_timestamp:
end_timestamp = timeutils.parse_isotime(end_timestamp)
end_timestamp = end_timestamp.replace(tzinfo=None)
query_end = end_timestamp + datetime.timedelta(minutes=search_offset)
else:
query_end = None
return dict(query_start=query_start,
query_end=query_end,
start_timestamp=start_timestamp,
end_timestamp=end_timestamp,
search_offset=search_offset,
)
@blueprint.route('/resources/<resource>/meters/<meter>/duration')
def compute_duration_by_resource(resource, meter):
"""Return the earliest timestamp, last timestamp,
and duration for the resource and meter.
:param resource: The ID of the resource.
:param meter: The name of the meter.
:param start_timestamp: ISO-formatted string of the
earliest timestamp to return.
:param end_timestamp: ISO-formatted string of the
latest timestamp to return.
:param search_offset: Number of minutes before
and after start and end timestamps to query.
"""
q_ts = _get_query_timestamps(flask.request.args)
start_timestamp = q_ts['start_timestamp']
end_timestamp = q_ts['end_timestamp']
# Query the database for the interval of timestamps
# within the desired range.
f = storage.SampleFilter(
meter=meter,
project=acl.get_limited_to_project(flask.request.headers),
resource=resource,
start=q_ts['query_start'],
end=q_ts['query_end'],
)
stats = flask.request.storage_conn.get_meter_statistics(f)
min_ts, max_ts = stats.duration_start, stats.duration_end
# "Clamp" the timestamps we return to the original time
# range, excluding the offset.
LOG.debug(_('start_timestamp %(start_timestamp)s, '
'end_timestamp %(end_timestamp)s, '
'min_ts %(min_ts)s, '
'max_ts %(max_ts)s') % (
{'start_timestamp': start_timestamp,
'end_timestamp': end_timestamp,
'min_ts': min_ts,
'max_ts': max_ts}))
if start_timestamp and min_ts and min_ts < start_timestamp:
min_ts = start_timestamp
LOG.debug(_('clamping min timestamp to range'))
if end_timestamp and max_ts and max_ts > end_timestamp:
max_ts = end_timestamp
LOG.debug(_('clamping max timestamp to range'))
# If we got valid timestamps back, compute a duration in minutes.
#
# If the min > max after clamping then we know the
# timestamps on the samples fell outside of the time
# range we care about for the query, so treat them as
# "invalid."
#
# If the timestamps are invalid, return None as a
# sentinal indicating that there is something "funny"
# about the range.
if min_ts and max_ts and (min_ts <= max_ts):
duration = timeutils.delta_seconds(min_ts, max_ts)
else:
min_ts = max_ts = duration = None
return flask.jsonify(start_timestamp=min_ts,
end_timestamp=max_ts,
duration=duration,
)
def _get_statistics(stats_type, meter=None, resource=None, project=None):
q_ts = _get_query_timestamps(flask.request.args)
f = storage.SampleFilter(
meter=meter,
project=project,
resource=resource,
start=q_ts['query_start'],
end=q_ts['query_end'],
)
# TODO(sberler): do we want to return an error if the resource
# does not exist?
results = list(flask.request.storage_conn.get_meter_statistics(f))
value = None
if results:
value = getattr(results[0], stats_type) # there should only be one!
return flask.jsonify(volume=value)
@blueprint.route('/resources/<resource>/meters/<meter>/volume/max')
def compute_max_resource_volume(resource, meter):
"""Return the max volume for a meter.
:param resource: The ID of the resource.
:param meter: The name of the meter.
:param start_timestamp: ISO-formatted string of the
earliest time to include in the calculation.
:param end_timestamp: ISO-formatted string of the
latest time to include in the calculation.
:param search_offset: Number of minutes before and
after start and end timestamps to query.
"""
return _get_statistics(
'max',
meter=meter,
resource=resource,
project=acl.get_limited_to_project(flask.request.headers),
)
@blueprint.route('/resources/<resource>/meters/<meter>/volume/sum')
def compute_resource_volume_sum(resource, meter):
"""Return the sum of samples for a meter.
:param resource: The ID of the resource.
:param meter: The name of the meter.
:param start_timestamp: ISO-formatted string of the
earliest time to include in the calculation.
:param end_timestamp: ISO-formatted string of the
latest time to include in the calculation.
:param search_offset: Number of minutes before and
after start and end timestamps to query.
"""
return _get_statistics(
'sum',
meter=meter,
resource=resource,
project=acl.get_limited_to_project(flask.request.headers),
)
@blueprint.route('/projects/<project>/meters/<meter>/volume/max')
def compute_project_volume_max(project, meter):
"""Return the max volume for a meter.
:param project: The ID of the project.
:param meter: The name of the meter.
:param start_timestamp: ISO-formatted string of the
earliest time to include in the calculation.
:param end_timestamp: ISO-formatted string of the
latest time to include in the calculation.
:param search_offset: Number of minutes before and
after start and end timestamps to query.
"""
check_authorized_project(project)
return _get_statistics('max', project=project, meter=meter)
@blueprint.route('/projects/<project>/meters/<meter>/volume/sum')
def compute_project_volume_sum(project, meter):
"""Return the total volume for a meter.
:param project: The ID of the project.
:param meter: The name of the meter.
:param start_timestamp: ISO-formatted string of the
earliest time to include in the calculation.
:param end_timestamp: ISO-formatted string of the
latest time to include in the calculation.
:param search_offset: Number of minutes before and
after start and end timestamps to query.
"""
check_authorized_project(project)
return _get_statistics(
'sum',
meter=meter,
project=project,
)

View File

@ -1,26 +0,0 @@
Copyright (c) 2012, Michael Bostock
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* The name Michael Bostock may not be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL MICHAEL BOSTOCK BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@ -1,7 +0,0 @@
Copyright (C) 2011 by Shutterstock Images, LLC
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,307 +0,0 @@
.rickshaw_graph .detail {
pointer-events: none;
position: absolute;
top: 0;
z-index: 2;
background: rgba(0, 0, 0, 0.1);
bottom: 0;
width: 1px;
transition: opacity 0.25s linear;
-moz-transition: opacity 0.25s linear;
-o-transition: opacity 0.25s linear;
-webkit-transition: opacity 0.25s linear;
}
.rickshaw_graph .detail.inactive {
opacity: 0;
}
.rickshaw_graph .detail .item.active {
opacity: 1;
}
.rickshaw_graph .detail .x_label {
font-family: Arial, sans-serif;
border-radius: 3px;
padding: 6px;
opacity: 0.5;
border: 1px solid #e0e0e0;
font-size: 12px;
position: absolute;
background: white;
white-space: nowrap;
}
.rickshaw_graph .detail .item {
position: absolute;
z-index: 2;
border-radius: 3px;
padding: 0.25em;
font-size: 12px;
font-family: Arial, sans-serif;
opacity: 0;
background: rgba(0, 0, 0, 0.4);
color: white;
border: 1px solid rgba(0, 0, 0, 0.4);
margin-left: 1em;
margin-top: -1em;
white-space: nowrap;
}
.rickshaw_graph .detail .item.active {
opacity: 1;
background: rgba(0, 0, 0, 0.8);
}
.rickshaw_graph .detail .item:before {
content: "\25c2";
position: absolute;
left: -0.5em;
color: rgba(0, 0, 0, 0.7);
width: 0;
}
.rickshaw_graph .detail .dot {
width: 4px;
height: 4px;
margin-left: -4px;
margin-top: -3px;
border-radius: 5px;
position: absolute;
box-shadow: 0 0 2px rgba(0, 0, 0, 0.6);
background: white;
border-width: 2px;
border-style: solid;
display: none;
background-clip: padding-box;
}
.rickshaw_graph .detail .dot.active {
display: block;
}
/* graph */
.rickshaw_graph {
position: relative;
}
.rickshaw_graph svg {
display: block;
overflow: hidden;
}
/* ticks */
.rickshaw_graph .x_tick {
position: absolute;
top: 0;
bottom: 0;
width: 0px;
border-left: 1px dotted rgba(0, 0, 0, 0.2);
pointer-events: none;
}
.rickshaw_graph .x_tick .title {
position: absolute;
font-size: 12px;
font-family: Arial, sans-serif;
opacity: 0.5;
white-space: nowrap;
margin-left: 3px;
bottom: 1px;
}
/* annotations */
.rickshaw_annotation_timeline {
height: 1px;
border-top: 1px solid #e0e0e0;
margin-top: 10px;
position: relative;
}
.rickshaw_annotation_timeline .annotation {
position: absolute;
height: 6px;
width: 6px;
margin-left: -2px;
top: -3px;
border-radius: 5px;
background-color: rgba(0, 0, 0, 0.25);
}
.rickshaw_graph .annotation_line {
position: absolute;
top: 0;
bottom: -6px;
width: 0px;
border-left: 2px solid rgba(0, 0, 0, 0.3);
display: none;
}
.rickshaw_graph .annotation_line.active {
display: block;
}
.rickshaw_graph .annotation_range {
background: rgba(0, 0, 0, 0.1);
display: none;
position: absolute;
top: 0;
bottom: -6px;
z-index: -10;
}
.rickshaw_graph .annotation_range.active {
display: block;
}
.rickshaw_graph .annotation_range.active.offscreen {
display: none;
}
.rickshaw_annotation_timeline .annotation .content {
background: white;
color: black;
opacity: 0.9;
padding: 5px 5px;
box-shadow: 0 0 2px rgba(0, 0, 0, 0.8);
border-radius: 3px;
position: relative;
z-index: 20;
font-size: 12px;
padding: 6px 8px 8px;
top: 18px;
left: -11px;
width: 160px;
display: none;
cursor: pointer;
}
.rickshaw_annotation_timeline .annotation .content:before {
content: "\25b2";
position: absolute;
top: -11px;
color: white;
text-shadow: 0 -1px 1px rgba(0, 0, 0, 0.8);
}
.rickshaw_annotation_timeline .annotation.active,
.rickshaw_annotation_timeline .annotation:hover {
background-color: rgba(0, 0, 0, 0.8);
cursor: none;
}
.rickshaw_annotation_timeline .annotation .content:hover {
z-index: 50;
}
.rickshaw_annotation_timeline .annotation.active .content {
display: block;
}
.rickshaw_annotation_timeline .annotation:hover .content {
display: block;
z-index: 50;
}
.rickshaw_graph .y_axis {
fill: none;
}
.rickshaw_graph .y_ticks .tick {
stroke: rgba(0, 0, 0, 0.16);
stroke-width: 2px;
shape-rendering: crisp-edges;
pointer-events: none;
}
.rickshaw_graph .y_grid .tick {
z-index: -1;
stroke: rgba(0, 0, 0, 0.20);
stroke-width: 1px;
stroke-dasharray: 1 1;
}
.rickshaw_graph .y_grid path {
fill: none;
stroke: none;
}
.rickshaw_graph .y_ticks path {
fill: none;
stroke: #808080;
}
.rickshaw_graph .y_ticks text {
opacity: 0.5;
font-size: 12px;
pointer-events: none;
}
.rickshaw_graph .x_tick.glow .title,
.rickshaw_graph .y_ticks.glow text {
fill: black;
color: black;
text-shadow:
-1px 1px 0 rgba(255, 255, 255, 0.1),
1px -1px 0 rgba(255, 255, 255, 0.1),
1px 1px 0 rgba(255, 255, 255, 0.1),
0px 1px 0 rgba(255, 255, 255, 0.1),
0px -1px 0 rgba(255, 255, 255, 0.1),
1px 0px 0 rgba(255, 255, 255, 0.1),
-1px 0px 0 rgba(255, 255, 255, 0.1),
-1px -1px 0 rgba(255, 255, 255, 0.1);
}
.rickshaw_graph .x_tick.inverse .title,
.rickshaw_graph .y_ticks.inverse text {
fill: white;
color: white;
text-shadow:
-1px 1px 0 rgba(0, 0, 0, 0.8),
1px -1px 0 rgba(0, 0, 0, 0.8),
1px 1px 0 rgba(0, 0, 0, 0.8),
0px 1px 0 rgba(0, 0, 0, 0.8),
0px -1px 0 rgba(0, 0, 0, 0.8),
1px 0px 0 rgba(0, 0, 0, 0.8),
-1px 0px 0 rgba(0, 0, 0, 0.8),
-1px -1px 0 rgba(0, 0, 0, 0.8);
}
.rickshaw_legend {
font-family: Arial;
font-size: 12px;
color: white;
background: #404040;
display: inline-block;
padding: 12px 5px;
border-radius: 2px;
position: relative;
}
.rickshaw_legend:hover {
z-index: 10;
}
.rickshaw_legend .swatch {
width: 10px;
height: 10px;
border: 1px solid rgba(0, 0, 0, 0.2);
}
.rickshaw_legend .line {
clear: both;
line-height: 140%;
padding-right: 15px;
}
.rickshaw_legend .line .swatch {
display: inline-block;
margin-right: 3px;
border-radius: 2px;
}
.rickshaw_legend .label {
white-space: nowrap;
display: inline;
}
.rickshaw_legend .action:hover {
opacity: 0.6;
}
.rickshaw_legend .action {
margin-right: 0.2em;
font-size: 10px;
opacity: 0.2;
cursor: pointer;
font-size: 14px;
}
.rickshaw_legend .line.disabled {
opacity: 0.4;
}
.rickshaw_legend ul {
list-style-type: none;
margin: 0;
padding: 0;
margin: 2px;
cursor: pointer;
}
.rickshaw_legend li {
padding: 0 0 0 2px;
min-width: 80px;
white-space: nowrap;
}
.rickshaw_legend li:hover {
background: rgba(255, 255, 255, 0.08);
border-radius: 3px;
}
.rickshaw_legend li:active {
background: rgba(255, 255, 255, 0.2);
border-radius: 3px;
}

File diff suppressed because it is too large Load Diff

View File

@ -1,175 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<title>
Metering for {{meter}}
</title>
<link href="/v1/static/bootstrap/css/bootstrap.css" rel="stylesheet" type="text/css">
<link href="/v1/static/bootstrap/css/bootstrap-responsive.css" rel="stylesheet" type="text/css">
<link href="/v1/static/rickshaw.css" rel="stylesheet" type="text/css">
</head>
<body>
<div class="container">
<div class="content">
<div>
<ul class="breadcrumb">
{% if source %}
<li class="active">
<a href="/v1/sources/{{source}}">
<i class="icon-share"></i>
Source {{source}}
</a>
<span class="divider">/</span>
</li>
{% endif %}
{% if user %}
<li class="active">
<a href="/v1/users/{{user}}">
<i class="icon-user"></i>
User {{user}}
</a>
<span class="divider">/</span>
</li>
{% endif %}
{% if project %}
<li class="active">
<a href="/v1/projects/{{project}}">
<i class="icon-tasks"></i>
Project <strong>{{project}}</strong>
</a>
<span class="divider">/</span>
</li>
{% endif %}
{% if resource %}
<li>
<a href="/v1/resources/{{resource}}">
<i class="icon-cog"></i>
Resource
{{resource}}
</a>
<span class="divider">/</span>
</li>
{% endif %}
<li class="active">
<a href="#">
<i class="icon-screenshot"></i>
Meter
{{meter}}
</a>
</li>
</ul>
</div>
<div class="row">
<div class="span7">
<h1>Graph</h1>
<div id="chart"></div>
</div>
<div class="span5">
<h1>API</h1>
<div class="btn-group" id="api-buttons">
</div>
<br>
<div id="result"></div>
</div>
</div>
<h1>JSON</h1>
<pre class="pre-scrollable" id="events-json">
</pre>
</div>
</div>
<script src="/v1/static/bootstrap/js/bootstrap.js" type="text/javascript"></script>
<script src="/v1/static/jquery-1.8.3.js" type="text/javascript"></script>
<script src="/v1/static/d3.v2.js" type="text/javascript"></script>
<script src="/v1/static/rickshaw.js" type="text/javascript"></script>
<script type="text/javascript">
$(function () {
var events = {{events.data|safe}};
$("pre#events-json").text(JSON.stringify(events, undefined, 2));
var graph = new Rickshaw.Graph( {
element: document.getElementById("chart"),
renderer: 'line',
series: [
{
data: events.events.map(function (event) {
formatDate = d3.time.format.iso;
return {
x: formatDate.parse(event.timestamp).getTime(),
y: event.counter_volume,
}
}),
color: "#c05020",
name: "{{meter}}",
},
]
} );
var y_ticks = new Rickshaw.Graph.Axis.Y( {
graph: graph,
orientation: 'left',
tickFormat: Rickshaw.Fixtures.Number.formatKMBT,
element: document.getElementById('y_axis'),
} );
var axes = new Rickshaw.Graph.Axis.Time({
graph: graph,
ticksTreatment: "glow",
});
var hoverDetail = new Rickshaw.Graph.HoverDetail({
graph: graph
});
graph.render();
})
</script>
<script type="text/javascript">
$(function () {
var meter_api = [["volume/max", "volume-max", "chevron-up"],
["volume/sum", "volume-sum", "plus-sign"],
["duration", "duration", "time"]];
meter_api.forEach(function (data) {
var link = data[0];
var class_name = data[1];
var icon = data[2];
$("#api-buttons")
.append($("<a>")
.attr({
href: "./{{meter}}/" + link,
id: "button-" + class_name,
})
.addClass("btn btn-primary")
.append($("<i>").addClass("icon-white icon-" + icon))
.append(" Get " + link)
.click(function (event) {
event.preventDefault();
$.ajax({
url: "./{{meter}}/" + link,
}).done(function (data) {
$("#result")
.empty()
.append($("<div>")
.addClass("well")
.append($("<strong>")
.append($("<i>").addClass("icon-" + icon))
.append(" " + link))
.append($("<br>"))
.append($("<pre>")
.append(JSON.stringify(data,
undefined, 2))))
})
}))
});
});
</script>
</body>
</html>

View File

@ -173,22 +173,6 @@ class Connection(object):
"""
raise NotImplementedError('Clearing samples not implemented')
@staticmethod
def get_users(source=None):
"""Return an iterable of user id strings.
:param source: Optional source filter.
"""
raise NotImplementedError('Users not implemented')
@staticmethod
def get_projects(source=None):
"""Return an iterable of project id strings.
:param source: Optional source filter.
"""
raise NotImplementedError('Projects not implemented')
@staticmethod
def get_resources(user=None, project=None, source=None,
start_timestamp=None, start_timestamp_op=None,

View File

@ -334,32 +334,6 @@ class Connection(base.Connection):
)})
meter_table.put(row, record)
def get_users(self, source=None):
"""Return an iterable of user id strings.
:param source: Optional source filter.
"""
with self.conn_pool.connection() as conn:
user_table = conn.table(self.USER_TABLE)
LOG.debug(_("Query User table: source=%s") % source)
scan_args = {}
if source:
scan_args['columns'] = ['f:s_%s' % source]
return sorted(key for key, ignored in user_table.scan(**scan_args))
def get_projects(self, source=None):
"""Return an iterable of project id strings.
:param source: Optional source filter.
"""
with self.conn_pool.connection() as conn:
project_table = conn.table(self.PROJECT_TABLE)
LOG.debug(_("Query Project table: source=%s") % source)
scan_args = {}
if source:
scan_args['columns'] = ['f:s_%s' % source]
return (key for key, ignored in project_table.scan(**scan_args))
def get_resources(self, user=None, project=None, source=None,
start_timestamp=None, start_timestamp_op=None,
end_timestamp=None, end_timestamp_op=None,

View File

@ -56,20 +56,6 @@ class Connection(base.Connection):
"""
LOG.info(_("Dropping data with TTL %d"), ttl)
def get_users(self, source=None):
"""Return an iterable of user id strings.
:param source: Optional source filter.
"""
return []
def get_projects(self, source=None):
"""Return an iterable of project id strings.
:param source: Optional source filter.
"""
return []
def get_resources(self, user=None, project=None, source=None,
start_timestamp=None, start_timestamp_op=None,
end_timestamp=None, end_timestamp_op=None,

View File

@ -389,26 +389,6 @@ class Connection(base.Connection):
for res_obj in query.all():
session.delete(res_obj)
def get_users(self, source=None):
"""Return an iterable of user id strings.
:param source: Optional source filter.
"""
query = self._engine_facade.get_session().query(models.User.id)
if source is not None:
query = query.filter(models.User.sources.any(id=source))
return (x[0] for x in query.all())
def get_projects(self, source=None):
"""Return an iterable of project id strings.
:param source: Optional source filter.
"""
query = self._engine_facade.get_session().query(models.Project.id)
if source:
query = query.filter(models.Project.sources.any(id=source))
return (x[0] for x in query.all())
def get_resources(self, user=None, project=None, source=None,
start_timestamp=None, start_timestamp_op=None,
end_timestamp=None, end_timestamp_op=None,

View File

@ -146,32 +146,6 @@ class Connection(base.Connection):
CAPABILITIES = utils.update_nested(base.Connection.CAPABILITIES,
COMMON_AVAILABLE_CAPABILITIES)
def get_users(self, source=None):
"""Return an iterable of user id strings.
:param source: Optional source filter.
"""
q = {}
if source is not None:
q['source'] = source
return (doc['_id'] for doc in
self.db.user.find(q, fields=['_id'],
sort=[('_id', pymongo.ASCENDING)]))
def get_projects(self, source=None):
"""Return an iterable of project id strings.
:param source: Optional source filter.
"""
q = {}
if source is not None:
q['source'] = source
return (doc['_id'] for doc in
self.db.project.find(q, fields=['_id'],
sort=[('_id', pymongo.ASCENDING)]))
def get_meters(self, user=None, project=None, resource=None, source=None,
metaquery={}, pagination=None):
"""Return an iterable of models.Meter instances

View File

@ -18,63 +18,15 @@
"""Base classes for API tests.
"""
import flask
from oslo.config import cfg
import pecan
import pecan.testing
from six.moves import urllib
from ceilometer.api.v1 import app as v1_app
from ceilometer.api.v1 import blueprint as v1_blueprint
from ceilometer import messaging
from ceilometer.openstack.common import jsonutils
from ceilometer import service
from ceilometer.tests import db as db_test_base
OPT_GROUP_NAME = 'keystone_authtoken'
class TestBase(db_test_base.TestBase):
"""Use only for v1 API tests.
"""
def setUp(self):
super(TestBase, self).setUp()
messaging.setup("fake://")
self.addCleanup(messaging.cleanup)
service.prepare_service([])
self.CONF.set_override("auth_version",
"v2.0", group=OPT_GROUP_NAME)
self.CONF.set_override("policy_file",
self.path_get('etc/ceilometer/policy.json'))
sources_file = self.path_get('ceilometer/tests/sources.json')
self.app = v1_app.make_app(self.CONF,
attach_storage=False,
sources_file=sources_file)
# this is needed to pass over unhandled exceptions
self.app.debug = True
self.app.register_blueprint(v1_blueprint.blueprint)
self.test_app = self.app.test_client()
@self.app.before_request
def attach_storage_connection():
flask.request.storage_conn = self.conn
def get(self, path, headers=None, **kwds):
if kwds:
query = path + '?' + urllib.parse.urlencode(kwds)
else:
query = path
rv = self.test_app.get(query, headers=headers)
if rv.status_code == 200 and rv.content_type == 'application/json':
try:
data = jsonutils.loads(rv.data)
except ValueError:
print('RAW DATA:%s' % rv)
raise
return data
return rv
cfg.CONF.import_group(OPT_GROUP_NAME, "keystoneclient.middleware.auth_token")
class FunctionalTest(db_test_base.TestBase):

View File

@ -1,67 +0,0 @@
# -*- encoding: utf-8 -*-
#
# Copyright © 2013 Julien Danjou
#
# Author: Julien Danjou <julien@danjou.info>
#
# 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.
"""Test basic ceilometer-api app
"""
import os
from keystoneclient.middleware import auth_token
from ceilometer.api.v1 import app
from ceilometer import messaging
from ceilometer.openstack.common import fileutils
from ceilometer.openstack.common.fixture import config
from ceilometer.openstack.common import test
from ceilometer import service
from ceilometer.tests import api as acl
class TestApp(test.BaseTestCase):
def setUp(self):
super(TestApp, self).setUp()
self.CONF = self.useFixture(config.Config()).conf
messaging.setup('fake://')
self.addCleanup(messaging.cleanup)
def test_keystone_middleware_conf(self):
self.CONF.set_override("auth_protocol", "file",
group=acl.OPT_GROUP_NAME)
self.CONF.set_override("auth_version", "v2.0",
group=acl.OPT_GROUP_NAME)
self.CONF.set_override("auth_uri", None,
group=acl.OPT_GROUP_NAME)
api_app = app.make_app(self.CONF, attach_storage=False)
conf = dict(self.CONF.get(acl.OPT_GROUP_NAME))
api_app = auth_token.AuthProtocol(api_app,
conf=conf)
self.assertTrue(api_app.auth_uri.startswith('file'))
def test_keystone_middleware_parse_conffile(self):
content = "[{0}]\nauth_protocol = file"\
"\nauth_version = v2.0".format(acl.OPT_GROUP_NAME)
tmpfile = fileutils.write_to_tempfile(content=content,
prefix='ceilometer',
suffix='.conf')
service.prepare_service(['ceilometer-api',
'--config-file=%s' % tmpfile])
api_app = app.make_app(self.CONF, attach_storage=False)
conf = dict(self.CONF.get(acl.OPT_GROUP_NAME))
api_app = auth_token.AuthProtocol(api_app,
conf=conf)
self.assertTrue(api_app.auth_uri.startswith('file'))
os.unlink(tmpfile)

View File

@ -1,140 +0,0 @@
# -*- encoding: utf-8 -*-
#
# Copyright © 2012 New Dream Network, LLC (DreamHost)
#
# Author: Doug Hellmann <doug.hellmann@dreamhost.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.
"""Test listing raw events.
"""
import datetime
import mock
from ceilometer.openstack.common import timeutils
from ceilometer.storage import models
from ceilometer.tests import api as tests_api
from ceilometer.tests import db as tests_db
class TestComputeDurationByResource(tests_api.TestBase,
tests_db.MixinTestsWithBackendScenarios):
def setUp(self):
super(TestComputeDurationByResource, self).setUp()
# Create events relative to the range and pretend
# that the intervening events exist.
self.early1 = datetime.datetime(2012, 8, 27, 7, 0)
self.early2 = datetime.datetime(2012, 8, 27, 17, 0)
self.start = datetime.datetime(2012, 8, 28, 0, 0)
self.middle1 = datetime.datetime(2012, 8, 28, 8, 0)
self.middle2 = datetime.datetime(2012, 8, 28, 18, 0)
self.end = datetime.datetime(2012, 8, 28, 23, 59)
self.late1 = datetime.datetime(2012, 8, 29, 9, 0)
self.late2 = datetime.datetime(2012, 8, 29, 19, 0)
def _patch_get_stats(self, start, end):
statitics = models.Statistics(unit='',
min=0, max=0, avg=0, sum=0, count=0,
period=None,
period_start=None,
period_end=None,
duration=end - start,
duration_start=start,
duration_end=end,
groupby=None)
return mock.patch.object(self.conn, 'get_meter_statistics',
return_value=statitics)
def _invoke_api(self):
return self.get(
'/resources/resource-id/meters/instance:m1.tiny/duration',
start_timestamp=self.start.isoformat(),
end_timestamp=self.end.isoformat(),
search_offset=10, # this value doesn't matter, db call is mocked
)
def test_before_range(self):
with self._patch_get_stats(self.early1, self.early2):
data = self._invoke_api()
self.assertIsNone(data['start_timestamp'])
self.assertIsNone(data['end_timestamp'])
self.assertIsNone(data['duration'])
def _assert_times_match(self, actual, expected):
actual = timeutils.parse_isotime(actual).replace(tzinfo=None)
self.assertEqual(expected, actual)
def test_overlap_range_start(self):
with self._patch_get_stats(self.early1, self.middle1):
data = self._invoke_api()
self._assert_times_match(data['start_timestamp'], self.start)
self._assert_times_match(data['end_timestamp'], self.middle1)
self.assertEqual(8 * 60 * 60, data['duration'])
def test_within_range(self):
with self._patch_get_stats(self.middle1, self.middle2):
data = self._invoke_api()
self._assert_times_match(data['start_timestamp'], self.middle1)
self._assert_times_match(data['end_timestamp'], self.middle2)
self.assertEqual(10 * 60 * 60, data['duration'])
def test_within_range_zero_duration(self):
with self._patch_get_stats(self.middle1, self.middle1):
data = self._invoke_api()
self._assert_times_match(data['start_timestamp'], self.middle1)
self._assert_times_match(data['end_timestamp'], self.middle1)
self.assertEqual(0, data['duration'])
def test_overlap_range_end(self):
with self._patch_get_stats(self.middle2, self.late1):
data = self._invoke_api()
self._assert_times_match(data['start_timestamp'], self.middle2)
self._assert_times_match(data['end_timestamp'], self.end)
self.assertEqual(((6 * 60) - 1) * 60, data['duration'])
def test_after_range(self):
with self._patch_get_stats(self.late1, self.late2):
data = self._invoke_api()
self.assertIsNone(data['start_timestamp'])
self.assertIsNone(data['end_timestamp'])
self.assertIsNone(data['duration'])
def test_without_end_timestamp(self):
with self._patch_get_stats(self.late1, self.late2):
data = self.get(
'/resources/resource-id/meters/instance:m1.tiny/duration',
start_timestamp=self.late1.isoformat(),
# this value doesn't matter, db call is mocked
search_offset=10,
)
self._assert_times_match(data['start_timestamp'], self.late1)
self._assert_times_match(data['end_timestamp'], self.late2)
def test_without_start_timestamp(self):
with self._patch_get_stats(self.early1, self.early2):
data = self.get(
'/resources/resource-id/meters/instance:m1.tiny/duration',
end_timestamp=self.early2.isoformat(),
# this value doesn't matter, db call is mocked
search_offset=10,
)
self._assert_times_match(data['start_timestamp'], self.early1)
self._assert_times_match(data['end_timestamp'], self.early2)

View File

@ -1,81 +0,0 @@
# -*- encoding: utf-8 -*-
#
# Copyright © 2012 New Dream Network, LLC (DreamHost)
#
# Author: Steven Berler <steven.berler@dreamhost.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.
"""Test the _get_query_timestamps helper function.
"""
import datetime
from ceilometer.api.v1 import blueprint
from ceilometer.openstack.common import test
class TestQueryTimestamps(test.BaseTestCase):
def test_get_query_timestamps_none_specified(self):
result = blueprint._get_query_timestamps()
expected = {'start_timestamp': None,
'end_timestamp': None,
'query_start': None,
'query_end': None,
'search_offset': 0,
}
self.assertEqual(expected, result)
def test_get_query_timestamps_start(self):
args = {'start_timestamp': '2012-09-20T12:13:14'}
result = blueprint._get_query_timestamps(args)
expected = {'start_timestamp': datetime.datetime(2012, 9, 20,
12, 13, 14),
'end_timestamp': None,
'query_start': datetime.datetime(2012, 9, 20,
12, 13, 14),
'query_end': None,
'search_offset': 0,
}
self.assertEqual(expected, result)
def test_get_query_timestamps_end(self):
args = {'end_timestamp': '2012-09-20T12:13:14'}
result = blueprint._get_query_timestamps(args)
expected = {'end_timestamp': datetime.datetime(2012, 9, 20,
12, 13, 14),
'start_timestamp': None,
'query_end': datetime.datetime(2012, 9, 20,
12, 13, 14),
'query_start': None,
'search_offset': 0,
}
self.assertEqual(expected, result)
def test_get_query_timestamps_with_offset(self):
args = {'start_timestamp': '2012-09-20T12:13:14',
'end_timestamp': '2012-09-20T13:24:25',
'search_offset': '20',
}
result = blueprint._get_query_timestamps(args)
expected = {'query_end': datetime.datetime(2012, 9, 20,
13, 44, 25),
'query_start': datetime.datetime(2012, 9, 20,
11, 53, 14),
'end_timestamp': datetime.datetime(2012, 9, 20,
13, 24, 25),
'start_timestamp': datetime.datetime(2012, 9, 20,
12, 13, 14),
'search_offset': 20,
}
self.assertEqual(expected, result)

View File

@ -1,216 +0,0 @@
# -*- encoding: utf-8 -*-
#
# Copyright © 2012 New Dream Network, LLC (DreamHost)
#
# Author: Doug Hellmann <doug.hellmann@dreamhost.com>
# Julien Danjou <julien@danjou.info>
#
# 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.
"""Test listing raw events.
"""
import datetime
from ceilometer.publisher import utils
from ceilometer import sample
from ceilometer.tests import api as tests_api
from ceilometer.tests import db as tests_db
class TestListEvents(tests_api.TestBase,
tests_db.MixinTestsWithBackendScenarios):
def setUp(self):
super(TestListEvents, self).setUp()
for cnt in [
sample.Sample(
'instance',
'cumulative',
'',
1,
'user-id',
'project1',
'resource-id',
timestamp=datetime.datetime(2012, 7, 2, 10, 40),
resource_metadata={'display_name': 'test-server',
'tag': 'self.sample'},
source='source1',
),
sample.Sample(
'instance',
'cumulative',
'',
2,
'user-id',
'project1',
'resource-id',
timestamp=datetime.datetime(2012, 7, 2, 10, 41),
resource_metadata={'display_name': 'test-server',
'tag': 'self.sample'},
source='source1',
),
sample.Sample(
'instance',
'cumulative',
'',
1,
'user-id2',
'project2',
'resource-id-alternate',
timestamp=datetime.datetime(2012, 7, 2, 10, 42),
resource_metadata={'display_name': 'test-server',
'tag': 'self.sample2'},
source='source1',
),
]:
msg = utils.meter_message_from_counter(
cnt,
self.CONF.publisher.metering_secret)
self.conn.record_metering_data(msg)
def test_empty_project(self):
data = self.get('/projects/no-such-project/meters/instance')
self.assertEqual({'events': []}, data)
def test_by_project(self):
data = self.get('/projects/project1/meters/instance')
self.assertEqual(2, len(data['events']))
def test_by_project_non_admin(self):
data = self.get('/projects/project1/meters/instance',
headers={"X-Roles": "Member",
"X-Project-Id": "project1"})
self.assertEqual(2, len(data['events']))
def test_by_project_wrong_tenant(self):
resp = self.get('/projects/project1/meters/instance',
headers={"X-Roles": "Member",
"X-Project-Id": "this-is-my-project"})
self.assertEqual(404, resp.status_code)
def test_by_project_with_timestamps(self):
data = self.get('/projects/project1/meters/instance',
start_timestamp=datetime.datetime(2012, 7, 2, 10, 42))
self.assertEqual(0, len(data['events']))
def test_empty_resource(self):
data = self.get('/resources/no-such-resource/meters/instance')
self.assertEqual({'events': []}, data)
def test_by_resource(self):
data = self.get('/resources/resource-id/meters/instance')
self.assertEqual(2, len(data['events']))
def test_by_resource_non_admin(self):
data = self.get('/resources/resource-id-alternate/meters/instance',
headers={"X-Roles": "Member",
"X-Project-Id": "project2"})
self.assertEqual(1, len(data['events']))
def test_by_resource_some_tenant(self):
data = self.get('/resources/resource-id/meters/instance',
headers={"X-Roles": "Member",
"X-Project-Id": "project2"})
self.assertEqual(0, len(data['events']))
def test_empty_source(self):
data = self.get('/sources/no-such-source/meters/instance')
self.assertEqual({'events': []}, data)
def test_by_source(self):
data = self.get('/sources/source1/meters/instance')
self.assertEqual(3, len(data['events']))
def test_by_source_non_admin(self):
data = self.get('/sources/source1/meters/instance',
headers={"X-Roles": "Member",
"X-Project-Id": "project2"})
self.assertEqual(1, len(data['events']))
def test_by_source_with_timestamps(self):
data = self.get('/sources/source1/meters/instance',
end_timestamp=datetime.datetime(2012, 7, 2, 10, 42))
self.assertEqual(2, len(data['events']))
def test_empty_user(self):
data = self.get('/users/no-such-user/meters/instance')
self.assertEqual({'events': []}, data)
def test_by_user(self):
data = self.get('/users/user-id/meters/instance')
self.assertEqual(2, len(data['events']))
def test_by_user_non_admin(self):
data = self.get('/users/user-id/meters/instance',
headers={"X-Roles": "Member",
"X-Project-Id": "project1"})
self.assertEqual(2, len(data['events']))
def test_by_user_wrong_tenant(self):
data = self.get('/users/user-id/meters/instance',
headers={"X-Roles": "Member",
"X-Project-Id": "project2"})
self.assertEqual(0, len(data['events']))
def test_by_user_with_timestamps(self):
data = self.get('/users/user-id/meters/instance',
start_timestamp=datetime.datetime(2012, 7, 2, 10, 41),
end_timestamp=datetime.datetime(2012, 7, 2, 10, 42))
self.assertEqual(1, len(data['events']))
def test_template_list_event(self):
rv = self.get('/resources/resource-id/meters/instance',
headers={"Accept": "text/html"})
self.assertEqual(200, rv.status_code)
self.assertTrue("text/html" in rv.content_type)
class TestListEventsMetaquery(TestListEvents,
tests_db.MixinTestsWithBackendScenarios):
def test_metaquery1(self):
q = '/sources/source1/meters/instance'
data = self.get('%s?metadata.tag=self.sample2' % q)
self.assertEqual(1, len(data['events']))
def test_metaquery1_wrong_tenant(self):
q = '/sources/source1/meters/instance'
data = self.get('%s?metadata.tag=self.sample2' % q,
headers={"X-Roles": "Member",
"X-Project-Id": "project1"})
self.assertEqual(0, len(data['events']))
def test_metaquery2(self):
q = '/sources/source1/meters/instance'
data = self.get('%s?metadata.tag=self.sample' % q)
self.assertEqual(2, len(data['events']))
def test_metaquery2_non_admin(self):
q = '/sources/source1/meters/instance'
data = self.get('%s?metadata.tag=self.sample' % q,
headers={"X-Roles": "Member",
"X-Project-Id": "project1"})
self.assertEqual(2, len(data['events']))
def test_metaquery3(self):
q = '/sources/source1/meters/instance'
data = self.get('%s?metadata.display_name=test-server' % q)
self.assertEqual(3, len(data['events']))
def test_metaquery3_with_project(self):
q = '/sources/source1/meters/instance'
data = self.get('%s?metadata.display_name=test-server' % q,
headers={"X-Roles": "Member",
"X-Project-Id": "project2"})
self.assertEqual(1, len(data['events']))

View File

@ -1,244 +0,0 @@
# -*- encoding: utf-8 -*-
#
# Copyright 2012 Red Hat, Inc.
#
# Author: Angus Salkeld <asalkeld@redhat.com>
# Julien Danjou <julien@danjou.info>
#
# 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.
"""Test listing meters.
"""
import datetime
import logging
from ceilometer.publisher import utils
from ceilometer import sample
from ceilometer.tests import api as tests_api
from ceilometer.tests import db as tests_db
LOG = logging.getLogger(__name__)
class TestListEmptyMeters(tests_api.TestBase,
tests_db.MixinTestsWithBackendScenarios):
def test_empty(self):
data = self.get('/meters')
self.assertEqual({'meters': []}, data)
class TestListMeters(tests_api.TestBase,
tests_db.MixinTestsWithBackendScenarios):
def setUp(self):
super(TestListMeters, self).setUp()
for cnt in [
sample.Sample(
'meter.test',
'cumulative',
'',
1,
'user-id',
'project-id',
'resource-id',
timestamp=datetime.datetime(2012, 7, 2, 10, 40),
resource_metadata={'display_name': 'test-server',
'tag': 'self.sample'},
source='test_list_resources'),
sample.Sample(
'meter.test',
'cumulative',
'',
3,
'user-id',
'project-id',
'resource-id',
timestamp=datetime.datetime(2012, 7, 2, 11, 40),
resource_metadata={'display_name': 'test-server',
'tag': 'self.sample'},
source='test_list_resources'),
sample.Sample(
'meter.mine',
'gauge',
'',
1,
'user-id',
'project-id',
'resource-id2',
timestamp=datetime.datetime(2012, 7, 2, 10, 41),
resource_metadata={'display_name': 'test-server',
'tag': 'two.sample'},
source='test_list_resources'),
sample.Sample(
'meter.test',
'cumulative',
'',
1,
'user-id2',
'project-id2',
'resource-id3',
timestamp=datetime.datetime(2012, 7, 2, 10, 42),
resource_metadata={'display_name': 'test-server',
'tag': 'three.sample'},
source='test_list_resources'),
sample.Sample(
'meter.mine',
'gauge',
'',
1,
'user-id4',
'project-id2',
'resource-id4',
timestamp=datetime.datetime(2012, 7, 2, 10, 43),
resource_metadata={'display_name': 'test-server',
'tag': 'four.sample'},
source='test_list_resources')]:
msg = utils.meter_message_from_counter(
cnt,
self.CONF.publisher.metering_secret)
self.conn.record_metering_data(msg)
def test_list_meters(self):
data = self.get('/meters')
self.assertEqual(4, len(data['meters']))
self.assertEqual(set(['resource-id',
'resource-id2',
'resource-id3',
'resource-id4']),
set(r['resource_id'] for r in data['meters']))
self.assertEqual(set(['meter.test', 'meter.mine']),
set(r['name'] for r in data['meters']))
def test_list_meters_non_admin(self):
data = self.get('/meters',
headers={"X-Roles": "Member",
"X-Project-Id": "project-id"})
self.assertEqual(2, len(data['meters']))
self.assertEqual(set(['resource-id', 'resource-id2']),
set(r['resource_id'] for r in data['meters']))
self.assertEqual(set(['meter.test', 'meter.mine']),
set(r['name'] for r in data['meters']))
def test_with_resource(self):
data = self.get('/resources/resource-id/meters')
ids = set(r['name'] for r in data['meters'])
self.assertEqual(set(['meter.test']), ids)
def test_with_source(self):
data = self.get('/sources/test_list_resources/meters')
ids = set(r['resource_id'] for r in data['meters'])
self.assertEqual(set(['resource-id',
'resource-id2',
'resource-id3',
'resource-id4']), ids)
def test_with_source_non_admin(self):
data = self.get('/sources/test_list_resources/meters',
headers={"X-Roles": "Member",
"X-Project-Id": "project-id2"})
ids = set(r['resource_id'] for r in data['meters'])
self.assertEqual(set(['resource-id3', 'resource-id4']), ids)
def test_with_source_non_existent(self):
data = self.get('/sources/test_list_resources_dont_exist/meters')
self.assertEqual([], data['meters'])
def test_with_user(self):
data = self.get('/users/user-id/meters')
nids = set(r['name'] for r in data['meters'])
self.assertEqual(set(['meter.mine', 'meter.test']), nids)
rids = set(r['resource_id'] for r in data['meters'])
self.assertEqual(set(['resource-id', 'resource-id2']), rids)
def test_with_user_non_admin(self):
data = self.get('/users/user-id/meters',
headers={"X-Roles": "Member",
"X-Project-Id": "project-id"})
nids = set(r['name'] for r in data['meters'])
self.assertEqual(set(['meter.mine', 'meter.test']), nids)
rids = set(r['resource_id'] for r in data['meters'])
self.assertEqual(set(['resource-id', 'resource-id2']), rids)
def test_with_user_wrong_tenant(self):
data = self.get('/users/user-id/meters',
headers={"X-Roles": "Member",
"X-Project-Id": "project666"})
self.assertEqual([], data['meters'])
def test_with_user_non_existent(self):
data = self.get('/users/user-id-foobar123/meters')
self.assertEqual([], data['meters'])
def test_with_project(self):
data = self.get('/projects/project-id2/meters')
ids = set(r['resource_id'] for r in data['meters'])
self.assertEqual(set(['resource-id3', 'resource-id4']), ids)
def test_with_project_non_admin(self):
data = self.get('/projects/project-id2/meters',
headers={"X-Roles": "Member",
"X-Project-Id": "project-id2"})
ids = set(r['resource_id'] for r in data['meters'])
self.assertEqual(set(['resource-id3', 'resource-id4']), ids)
def test_with_project_wrong_tenant(self):
data = self.get('/projects/project-id2/meters',
headers={"X-Roles": "Member",
"X-Project-Id": "project-id"})
self.assertEqual(404, data.status_code)
def test_with_project_non_existent(self):
data = self.get('/projects/jd-was-here/meters')
self.assertEqual([], data['meters'])
class TestListMetersMetaquery(TestListMeters,
tests_db.MixinTestsWithBackendScenarios):
def test_metaquery1(self):
data = self.get('/meters?metadata.tag=self.sample')
self.assertEqual(1, len(data['meters']))
def test_metaquery1_non_admin(self):
data = self.get('/meters?metadata.tag=self.sample',
headers={"X-Roles": "Member",
"X-Project-Id": "project-id"})
self.assertEqual(1, len(data['meters']))
def test_metaquery1_wrong_tenant(self):
data = self.get('/meters?metadata.tag=self.sample',
headers={"X-Roles": "Member",
"X-Project-Id": "project-666"})
self.assertEqual(0, len(data['meters']))
def test_metaquery2(self):
data = self.get('/meters?metadata.tag=four.sample')
self.assertEqual(1, len(data['meters']))
def test_metaquery2_non_admin(self):
data = self.get('/meters?metadata.tag=four.sample',
headers={"X-Roles": "Member",
"X-Project-Id": "project-id2"})
self.assertEqual(1, len(data['meters']))
def test_metaquery2_non_admin_wrong_project(self):
data = self.get('/meters?metadata.tag=four.sample',
headers={"X-Roles": "Member",
"X-Project-Id": "project-666"})
self.assertEqual(0, len(data['meters']))

View File

@ -1,103 +0,0 @@
# -*- encoding: utf-8 -*-
#
# Copyright © 2012 New Dream Network, LLC (DreamHost)
#
# Author: Doug Hellmann <doug.hellmann@dreamhost.com>
# Julien Danjou <julien@danjou.info>
#
# 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.
"""Test listing users.
"""
import datetime
import logging
from ceilometer.publisher import utils
from ceilometer import sample
from ceilometer.tests import api as tests_api
from ceilometer.tests import db as tests_db
LOG = logging.getLogger(__name__)
class TestListEmptyProjects(tests_api.TestBase,
tests_db.MixinTestsWithBackendScenarios):
def test_empty(self):
data = self.get('/projects')
self.assertEqual({'projects': []}, data)
class TestListProjects(tests_api.TestBase,
tests_db.MixinTestsWithBackendScenarios):
def setUp(self):
super(TestListProjects, self).setUp()
sample1 = sample.Sample(
'instance',
'cumulative',
'instance',
1,
'user-id',
'project-id',
'resource-id',
timestamp=datetime.datetime(2012, 7, 2, 10, 40),
resource_metadata={'display_name': 'test-server',
'tag': 'self.sample'},
source='test_list_projects',
)
msg = utils.meter_message_from_counter(
sample1,
self.CONF.publisher.metering_secret,
)
self.conn.record_metering_data(msg)
sample2 = sample.Sample(
'instance',
'cumulative',
'instance',
1,
'user-id2',
'project-id2',
'resource-id-alternate',
timestamp=datetime.datetime(2012, 7, 2, 10, 41),
resource_metadata={'display_name': 'test-server',
'tag': 'self.sample2'},
source='test_list_users',
)
msg2 = utils.meter_message_from_counter(
sample2,
self.CONF.publisher.metering_secret,
)
self.conn.record_metering_data(msg2)
def test_projects(self):
data = self.get('/projects')
self.assertEqual(['project-id', 'project-id2'], data['projects'])
def test_projects_non_admin(self):
data = self.get('/projects',
headers={"X-Roles": "Member",
"X-Project-Id": "project-id"})
self.assertEqual(['project-id'], data['projects'])
def test_with_source(self):
data = self.get('/sources/test_list_users/projects')
self.assertEqual(['project-id2'], data['projects'])
def test_with_source_non_admin(self):
data = self.get('/sources/test_list_users/projects',
headers={"X-Roles": "Member",
"X-Project-Id": "project-id2"})
self.assertEqual(['project-id2'], data['projects'])

View File

@ -1,288 +0,0 @@
# -*- encoding: utf-8 -*-
#
# Copyright © 2012 New Dream Network, LLC (DreamHost)
#
# Author: Doug Hellmann <doug.hellmann@dreamhost.com>
# Julien Danjou <julien@danjou.info>
#
# 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.
"""Test listing resources.
"""
import datetime
import logging
from ceilometer.publisher import utils
from ceilometer import sample
from ceilometer.tests import api as tests_api
from ceilometer.tests import db as tests_db
LOG = logging.getLogger(__name__)
class TestListEmptyResources(tests_api.TestBase,
tests_db.MixinTestsWithBackendScenarios):
def test_empty(self):
data = self.get('/resources')
self.assertEqual({'resources': []}, data)
class TestListResourcesBase(tests_api.TestBase,
tests_db.MixinTestsWithBackendScenarios):
def setUp(self):
super(TestListResourcesBase, self).setUp()
for cnt in [
sample.Sample(
'instance',
'cumulative',
'',
1,
'user-id',
'project-id',
'resource-id',
timestamp=datetime.datetime(2012, 7, 2, 10, 40),
resource_metadata={'display_name': 'test-server',
'tag': 'self.sample'},
source='test_list_resources',
),
sample.Sample(
'instance',
'cumulative',
'',
1,
'user-id',
'project-id',
'resource-id-alternate',
timestamp=datetime.datetime(2012, 7, 2, 10, 41),
resource_metadata={'display_name': 'test-server',
'tag': 'self.sample2'},
source='test_list_resources',
),
sample.Sample(
'instance',
'cumulative',
'',
1,
'user-id2',
'project-id2',
'resource-id2',
timestamp=datetime.datetime(2012, 7, 2, 10, 42),
resource_metadata={'display_name': 'test-server',
'tag': 'self.sample3'},
source='test_list_resources',
),
sample.Sample(
'instance',
'cumulative',
'',
1,
'user-id',
'project-id',
'resource-id',
timestamp=datetime.datetime(2012, 7, 2, 10, 43),
resource_metadata={'display_name': 'test-server',
'tag': 'self.sample4'},
source='test_list_resources',
)]:
msg = utils.meter_message_from_counter(
cnt,
self.CONF.publisher.metering_secret)
self.conn.record_metering_data(msg)
class TestListResources(TestListResourcesBase):
def test_list_resources(self):
data = self.get('/resources')
self.assertEqual(3, len(data['resources']))
self.assertEqual(set(['resource-id',
'resource-id-alternate',
'resource-id2']),
set(r['resource_id'] for r in data['resources']))
def test_list_resources_non_admin(self):
data = self.get('/resources',
headers={"X-Roles": "Member",
"X-Project-Id": "project-id"})
self.assertEqual(2, len(data['resources']))
self.assertEqual(set(['resource-id', 'resource-id-alternate']),
set(r['resource_id'] for r in data['resources']))
def test_list_resources_with_timestamps(self):
data = self.get('/resources',
start_timestamp=datetime.datetime(
2012, 7, 2, 10, 41).isoformat(),
end_timestamp=datetime.datetime(
2012, 7, 2, 10, 43).isoformat())
self.assertEqual(set(['resource-id-alternate', 'resource-id2']),
set(r['resource_id'] for r in data['resources']))
def test_list_resources_with_timestamps_non_admin(self):
data = self.get('/resources',
start_timestamp=datetime.datetime(
2012, 7, 2, 10, 41).isoformat(),
end_timestamp=datetime.datetime(
2012, 7, 2, 10, 43).isoformat(),
headers={"X-Roles": "Member",
"X-Project-Id": "project-id"})
self.assertEqual(set(['resource-id-alternate']),
set(r['resource_id'] for r in data['resources']))
def test_with_source(self):
data = self.get('/sources/test_list_resources/resources')
ids = set(r['resource_id'] for r in data['resources'])
self.assertEqual(set(['resource-id',
'resource-id2',
'resource-id-alternate']), ids)
def test_with_source_non_admin(self):
data = self.get('/sources/test_list_resources/resources',
headers={"X-Roles": "Member",
"X-Project-Id": "project-id"})
ids = set(r['resource_id'] for r in data['resources'])
self.assertEqual(set(['resource-id', 'resource-id-alternate']), ids)
def test_with_source_with_timestamps(self):
data = self.get('/sources/test_list_resources/resources',
start_timestamp=datetime.datetime(
2012, 7, 2, 10, 41).isoformat(),
end_timestamp=datetime.datetime(
2012, 7, 2, 10, 43).isoformat())
ids = set(r['resource_id'] for r in data['resources'])
self.assertEqual(set(['resource-id2', 'resource-id-alternate']), ids)
def test_with_source_with_timestamps_non_admin(self):
data = self.get('/sources/test_list_resources/resources',
headers={"X-Roles": "Member",
"X-Project-Id": "project-id"},
start_timestamp=datetime.datetime(
2012, 7, 2, 10, 41).isoformat(),
end_timestamp=datetime.datetime(
2012, 7, 2, 10, 43).isoformat())
ids = set(r['resource_id'] for r in data['resources'])
self.assertEqual(set(['resource-id-alternate']), ids)
def test_with_source_non_existent(self):
data = self.get('/sources/test_list_resources_dont_exist/resources')
self.assertEqual([], data['resources'])
def test_with_user(self):
data = self.get('/users/user-id/resources')
ids = set(r['resource_id'] for r in data['resources'])
self.assertEqual(set(['resource-id', 'resource-id-alternate']), ids)
def test_with_user_non_admin(self):
data = self.get('/users/user-id/resources',
headers={"X-Roles": "Member",
"X-Project-Id": "project-id"})
ids = set(r['resource_id'] for r in data['resources'])
self.assertEqual(set(['resource-id', 'resource-id-alternate']), ids)
def test_with_user_wrong_tenant(self):
data = self.get('/users/user-id/resources',
headers={"X-Roles": "Member",
"X-Project-Id": "project-jd"})
ids = set(r['resource_id'] for r in data['resources'])
self.assertEqual(set(), ids)
def test_with_user_with_timestamps(self):
data = self.get('/users/user-id/resources',
start_timestamp=datetime.datetime(
2012, 7, 2, 10, 42).isoformat(),
end_timestamp=datetime.datetime(
2012, 7, 2, 10, 42).isoformat())
ids = set(r['resource_id'] for r in data['resources'])
self.assertEqual(set(), ids)
def test_with_user_with_timestamps_non_admin(self):
data = self.get('/users/user-id/resources',
headers={"X-Roles": "Member",
"X-Project-Id": "project-id"},
start_timestamp=datetime.datetime(
2012, 7, 2, 10, 42).isoformat(),
end_timestamp=datetime.datetime(
2012, 7, 2, 10, 42).isoformat())
ids = set(r['resource_id'] for r in data['resources'])
self.assertEqual(set(), ids)
def test_with_user_non_existent(self):
data = self.get('/users/user-id-foobar123/resources')
self.assertEqual([], data['resources'])
def test_with_project(self):
data = self.get('/projects/project-id/resources')
ids = set(r['resource_id'] for r in data['resources'])
self.assertEqual(set(['resource-id', 'resource-id-alternate']), ids)
def test_with_project_non_admin(self):
data = self.get('/projects/project-id/resources',
headers={"X-Roles": "Member",
"X-Project-Id": "project-id"})
ids = set(r['resource_id'] for r in data['resources'])
self.assertEqual(set(['resource-id', 'resource-id-alternate']), ids)
def test_with_project_with_timestamp(self):
data = self.get('/projects/project-id/resources',
start_timestamp=datetime.datetime(
2012, 7, 2, 10, 40).isoformat(),
end_timestamp=datetime.datetime(
2012, 7, 2, 10, 41).isoformat())
ids = set(r['resource_id'] for r in data['resources'])
self.assertEqual(set(['resource-id']), ids)
def test_with_project_with_timestamp_non_admin(self):
data = self.get('/projects/project-id/resources',
headers={"X-Roles": "Member",
"X-Project-Id": "project-id"},
start_timestamp=datetime.datetime(
2012, 7, 2, 10, 40).isoformat(),
end_timestamp=datetime.datetime(
2012, 7, 2, 10, 41).isoformat())
ids = set(r['resource_id'] for r in data['resources'])
self.assertEqual(set(['resource-id']), ids)
def test_with_project_non_existent(self):
data = self.get('/projects/jd-was-here/resources')
self.assertEqual([], data['resources'])
class TestListResourcesMetaquery(TestListResourcesBase,
tests_db.MixinTestsWithBackendScenarios):
def test_metaquery1(self):
q = '/sources/test_list_resources/resources'
data = self.get('%s?metadata.display_name=test-server' % q)
self.assertEqual(3, len(data['resources']))
def test_metaquery1_non_admin(self):
q = '/sources/test_list_resources/resources'
data = self.get('%s?metadata.display_name=test-server' % q,
headers={"X-Roles": "Member",
"X-Project-Id": "project-id"})
self.assertEqual(2, len(data['resources']))
def test_metaquery2(self):
q = '/sources/test_list_resources/resources'
data = self.get('%s?metadata.tag=self.sample4' % q)
self.assertEqual(1, len(data['resources']))
def test_metaquery2_non_admin(self):
q = '/sources/test_list_resources/resources'
data = self.get('%s?metadata.tag=self.sample4' % q,
headers={"X-Roles": "Member",
"X-Project-Id": "project-id"})
self.assertEqual(1, len(data['resources']))

View File

@ -1,34 +0,0 @@
# -*- encoding: utf-8 -*-
#
# Copyright © 2012 Julien Danjou
#
# Author: Julien Danjou <julien@danjou.info>
#
# 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.
"""Test listing users.
"""
from ceilometer.tests import api as tests_api
from ceilometer.tests import db as tests_db
class TestListSource(tests_api.TestBase,
tests_db.MixinTestsWithBackendScenarios):
def test_source(self):
ydata = self.get('/sources/test_source')
self.assertIn("somekey", ydata)
self.assertEqual(666, ydata["somekey"])
def test_unknownsource(self):
ydata = self.get('/sources/test_source_that_does_not_exist')
self.assertEqual({}, ydata)

View File

@ -1,108 +0,0 @@
# -*- encoding: utf-8 -*-
#
# Copyright © 2012 New Dream Network, LLC (DreamHost)
#
# Author: Doug Hellmann <doug.hellmann@dreamhost.com>
# Julien Danjou <julien@danjou.info>
#
# 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.
"""Test listing users.
"""
import datetime
import logging
from ceilometer.publisher import utils
from ceilometer import sample
from ceilometer.tests import api as tests_api
from ceilometer.tests import db as tests_db
LOG = logging.getLogger(__name__)
class TestListEmptyUsers(tests_api.TestBase,
tests_db.MixinTestsWithBackendScenarios):
def test_empty(self):
data = self.get('/users')
self.assertEqual({'users': []}, data)
class TestListUsers(tests_api.TestBase,
tests_db.MixinTestsWithBackendScenarios):
def setUp(self):
super(TestListUsers, self).setUp()
sample1 = sample.Sample(
'instance',
'cumulative',
'instance',
1,
'user-id',
'project-id',
'resource-id',
timestamp=datetime.datetime(2012, 7, 2, 10, 40),
resource_metadata={'display_name': 'test-server',
'tag': 'self.sample',
},
source='test_list_users',
)
msg = utils.meter_message_from_counter(
sample1,
self.CONF.publisher.metering_secret,
)
self.conn.record_metering_data(msg)
sample2 = sample.Sample(
'instance',
'cumulative',
'',
1,
'user-id2',
'project-id',
'resource-id-alternate',
timestamp=datetime.datetime(2012, 7, 2, 10, 41),
resource_metadata={'display_name': 'test-server',
'tag': 'self.sample2',
},
source='not-test',
)
msg2 = utils.meter_message_from_counter(
sample2,
self.CONF.publisher.metering_secret,
)
self.conn.record_metering_data(msg2)
def test_users(self):
data = self.get('/users')
self.assertEqual(['user-id', 'user-id2'], data['users'])
def test_users_non_admin(self):
data = self.get('/users',
headers={"X-Roles": "Member",
"X-User-Id": "user-id",
"X-Project-Id": "project-id"})
self.assertEqual(['user-id'], data['users'])
def test_with_source(self):
data = self.get('/sources/test_list_users/users')
self.assertEqual(data['users'], ['user-id'])
def test_with_source_non_admin(self):
data = self.get('/sources/test_list_users/users',
headers={"X-Roles": "Member",
"X-User-Id": "user-id",
"X-Project-Id": "project-id"})
self.assertEqual(['user-id'], data['users'])

View File

@ -1,103 +0,0 @@
# -*- encoding: utf-8 -*-
#
# Copyright © 2012 New Dream Network, LLC (DreamHost)
#
# Author: Steven Berler <steven.berler@dreamhost.com>
# Julien Danjou <julien@danjou.info>
#
# 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.
"""Test getting the max resource volume.
"""
import datetime
from ceilometer.publisher import utils
from ceilometer import sample
from ceilometer.tests import api as tests_api
from ceilometer.tests import db as tests_db
class TestMaxProjectVolume(tests_api.TestBase,
tests_db.MixinTestsWithBackendScenarios):
def setUp(self):
super(TestMaxProjectVolume, self).setUp()
for i in range(3):
s = sample.Sample(
'volume.size',
'gauge',
'GiB',
5 + i,
'user-id',
'project1',
'resource-id-%s' % i,
timestamp=datetime.datetime(2012, 9, 25, 10 + i, 30 + i),
resource_metadata={'display_name': 'test-volume',
'tag': 'self.sample',
},
source='source1',
)
msg = utils.meter_message_from_counter(
s,
self.CONF.publisher.metering_secret,
)
self.conn.record_metering_data(msg)
def test_no_time_bounds(self):
data = self.get('/projects/project1/meters/volume.size/volume/max')
expected = {'volume': 7}
self.assertEqual(expected, data)
def test_no_time_bounds_non_admin(self):
data = self.get('/projects/project1/meters/volume.size/volume/max',
headers={"X-Roles": "Member",
"X-Project-Id": "project1"})
self.assertEqual({'volume': 7}, data)
def test_no_time_bounds_wrong_tenant(self):
resp = self.get('/projects/project1/meters/volume.size/volume/max',
headers={"X-Roles": "Member",
"X-Project-Id": "?"})
self.assertEqual(404, resp.status_code)
def test_start_timestamp(self):
data = self.get('/projects/project1/meters/volume.size/volume/max',
start_timestamp='2012-09-25T11:30:00')
expected = {'volume': 7}
self.assertEqual(expected, data)
def test_start_timestamp_after(self):
data = self.get('/projects/project1/meters/volume.size/volume/max',
start_timestamp='2012-09-25T12:34:00')
expected = {'volume': None}
self.assertEqual(expected, data)
def test_end_timestamp(self):
data = self.get('/projects/project1/meters/volume.size/volume/max',
end_timestamp='2012-09-25T11:30:00')
expected = {'volume': 5}
self.assertEqual(expected, data)
def test_end_timestamp_before(self):
data = self.get('/projects/project1/meters/volume.size/volume/max',
end_timestamp='2012-09-25T09:54:00')
expected = {'volume': None}
self.assertEqual(expected, data)
def test_start_end_timestamp(self):
data = self.get('/projects/project1/meters/volume.size/volume/max',
start_timestamp='2012-09-25T11:30:00',
end_timestamp='2012-09-25T11:32:00')
expected = {'volume': 6}
self.assertEqual(expected, data)

View File

@ -1,102 +0,0 @@
# -*- encoding: utf-8 -*-
#
# Copyright © 2012 New Dream Network, LLC (DreamHost)
#
# Author: Steven Berler <steven.berler@dreamhost.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.
"""Test getting the max resource volume.
"""
import datetime
from ceilometer.publisher import utils
from ceilometer import sample
from ceilometer.tests import api as tests_api
from ceilometer.tests import db as tests_db
class TestMaxResourceVolume(tests_api.TestBase,
tests_db.MixinTestsWithBackendScenarios):
def setUp(self):
super(TestMaxResourceVolume, self).setUp()
for i in range(3):
s = sample.Sample(
'volume.size',
'gauge',
'GiB',
5 + i,
'user-id',
'project1',
'resource-id',
timestamp=datetime.datetime(2012, 9, 25, 10 + i, 30 + i),
resource_metadata={'display_name': 'test-volume',
'tag': 'self.sample',
},
source='source1',
)
msg = utils.meter_message_from_counter(
s,
self.CONF.publisher.metering_secret,
)
self.conn.record_metering_data(msg)
def test_no_time_bounds(self):
data = self.get('/resources/resource-id/meters/volume.size/volume/max')
expected = {'volume': 7}
self.assertEqual(expected, data)
def test_no_time_bounds_non_admin(self):
data = self.get('/resources/resource-id/meters/volume.size/volume/max',
headers={"X-Roles": "Member",
"X-Project-Id": "project1"})
self.assertEqual({'volume': 7}, data)
def test_no_time_bounds_wrong_tenant(self):
data = self.get('/resources/resource-id/meters/volume.size/volume/max',
headers={"X-Roles": "Member",
"X-Project-Id": "??"})
self.assertEqual({'volume': None}, data)
def test_start_timestamp(self):
data = self.get('/resources/resource-id/meters/volume.size/volume/max',
start_timestamp='2012-09-25T11:30:00')
expected = {'volume': 7}
self.assertEqual(expected, data)
def test_start_timestamp_after(self):
data = self.get('/resources/resource-id/meters/volume.size/volume/max',
start_timestamp='2012-09-25T12:34:00')
expected = {'volume': None}
self.assertEqual(expected, data)
def test_end_timestamp(self):
data = self.get('/resources/resource-id/meters/volume.size/volume/max',
end_timestamp='2012-09-25T11:30:00')
expected = {'volume': 5}
self.assertEqual(expected, data)
def test_end_timestamp_before(self):
data = self.get('/resources/resource-id/meters/volume.size/volume/max',
end_timestamp='2012-09-25T09:54:00')
expected = {'volume': None}
self.assertEqual(expected, data)
def test_start_end_timestamp(self):
data = self.get('/resources/resource-id/meters/volume.size/volume/max',
start_timestamp='2012-09-25T11:30:00',
end_timestamp='2012-09-25T11:32:00')
expected = {'volume': 6}
self.assertEqual(expected, data)

View File

@ -1,103 +0,0 @@
# -*- encoding: utf-8 -*-
#
# Copyright © 2012 New Dream Network, LLC (DreamHost)
#
# Author: Steven Berler <steven.berler@dreamhost.com>
# Julien Danjou <julien@danjou.info>
#
# 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.
"""Test getting the sum project volume.
"""
import datetime
from ceilometer.publisher import utils
from ceilometer import sample
from ceilometer.tests import api as tests_api
from ceilometer.tests import db as tests_db
class TestSumProjectVolume(tests_api.TestBase,
tests_db.MixinTestsWithBackendScenarios):
def setUp(self):
super(TestSumProjectVolume, self).setUp()
for i in range(3):
s = sample.Sample(
'volume.size',
'gauge',
'GiB',
5 + i,
'user-id',
'project1',
'resource-id-%s' % i,
timestamp=datetime.datetime(2012, 9, 25, 10 + i, 30 + i),
resource_metadata={'display_name': 'test-volume',
'tag': 'self.sample',
},
source='source1',
)
msg = utils.meter_message_from_counter(
s,
self.CONF.publisher.metering_secret,
)
self.conn.record_metering_data(msg)
def test_no_time_bounds(self):
data = self.get('/projects/project1/meters/volume.size/volume/sum')
expected = {'volume': 5 + 6 + 7}
self.assertEqual(expected, data)
def test_no_time_bounds_non_admin(self):
data = self.get('/projects/project1/meters/volume.size/volume/sum',
headers={"X-Roles": "Member",
"X-Project-Id": "project1"})
self.assertEqual({'volume': 5 + 6 + 7}, data)
def test_no_time_bounds_wrong_tenant(self):
resp = self.get('/projects/project1/meters/volume.size/volume/sum',
headers={"X-Roles": "Member",
"X-Project-Id": "???"})
self.assertEqual(404, resp.status_code)
def test_start_timestamp(self):
data = self.get('/projects/project1/meters/volume.size/volume/sum',
start_timestamp='2012-09-25T11:30:00')
expected = {'volume': 6 + 7}
self.assertEqual(expected, data)
def test_start_timestamp_after(self):
data = self.get('/projects/project1/meters/volume.size/volume/sum',
start_timestamp='2012-09-25T12:34:00')
expected = {'volume': None}
self.assertEqual(expected, data)
def test_end_timestamp(self):
data = self.get('/projects/project1/meters/volume.size/volume/sum',
end_timestamp='2012-09-25T11:30:00')
expected = {'volume': 5}
self.assertEqual(expected, data)
def test_end_timestamp_before(self):
data = self.get('/projects/project1/meters/volume.size/volume/sum',
end_timestamp='2012-09-25T09:54:00')
expected = {'volume': None}
self.assertEqual(expected, data)
def test_start_end_timestamp(self):
data = self.get('/projects/project1/meters/volume.size/volume/sum',
start_timestamp='2012-09-25T11:30:00',
end_timestamp='2012-09-25T11:32:00')
expected = {'volume': 6}
self.assertEqual(expected, data)

View File

@ -1,103 +0,0 @@
# -*- encoding: utf-8 -*-
#
# Copyright © 2012 New Dream Network, LLC (DreamHost)
#
# Author: Doug Hellmann <doug.hellmann@dreamhost.com>
# Julien Danjou <julien@danjou.info>
#
# 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.
"""Test getting the total resource volume.
"""
import datetime
from ceilometer.publisher import utils
from ceilometer import sample
from ceilometer.tests import api as tests_api
from ceilometer.tests import db as tests_db
class TestSumResourceVolume(tests_api.TestBase,
tests_db.MixinTestsWithBackendScenarios):
def setUp(self):
super(TestSumResourceVolume, self).setUp()
for i in range(3):
s = sample.Sample(
'volume.size',
'gauge',
'GiB',
5 + i,
'user-id',
'project1',
'resource-id',
timestamp=datetime.datetime(2012, 9, 25, 10 + i, 30 + i),
resource_metadata={'display_name': 'test-volume',
'tag': 'self.sample',
},
source='source1',
)
msg = utils.meter_message_from_counter(
s,
self.CONF.publisher.metering_secret,
)
self.conn.record_metering_data(msg)
def test_no_time_bounds(self):
data = self.get('/resources/resource-id/meters/volume.size/volume/sum')
expected = {'volume': 5 + 6 + 7}
self.assertEqual(expected, data)
def test_no_time_bounds_non_admin(self):
data = self.get('/resources/resource-id/meters/volume.size/volume/sum',
headers={"X-Roles": "Member",
"X-Project-Id": "project1"})
self.assertEqual({'volume': 5 + 6 + 7}, data)
def test_no_time_bounds_wrong_tenant(self):
data = self.get('/resources/resource-id/meters/volume.size/volume/sum',
headers={"X-Roles": "Member",
"X-Project-Id": "?"})
self.assertEqual({'volume': None}, data)
def test_start_timestamp(self):
data = self.get('/resources/resource-id/meters/volume.size/volume/sum',
start_timestamp='2012-09-25T11:30:00')
expected = {'volume': 6 + 7}
self.assertEqual(expected, data)
def test_start_timestamp_after(self):
data = self.get('/resources/resource-id/meters/volume.size/volume/sum',
start_timestamp='2012-09-25T12:34:00')
expected = {'volume': None}
self.assertEqual(expected, data)
def test_end_timestamp(self):
data = self.get('/resources/resource-id/meters/volume.size/volume/sum',
end_timestamp='2012-09-25T11:30:00')
expected = {'volume': 5}
self.assertEqual(expected, data)
def test_end_timestamp_before(self):
data = self.get('/resources/resource-id/meters/volume.size/volume/sum',
end_timestamp='2012-09-25T09:54:00')
expected = {'volume': None}
self.assertEqual(expected, data)
def test_start_end_timestamp(self):
data = self.get('/resources/resource-id/meters/volume.size/volume/sum',
start_timestamp='2012-09-25T11:30:00',
end_timestamp='2012-09-25T11:32:00')
expected = {'volume': 6}
self.assertEqual(expected, data)

View File

@ -121,37 +121,6 @@ class DBTestBase(tests_db.TestBase):
)
class UserTest(DBTestBase,
tests_db.MixinTestsWithBackendScenarios):
def test_get_users(self):
users = self.conn.get_users()
expected = set(['user-id', 'user-id-alternate', 'user-id-2',
'user-id-3', 'user-id-4', 'user-id-5', 'user-id-6',
'user-id-7', 'user-id-8'])
self.assertEqual(set(users), expected)
def test_get_users_by_source(self):
users = self.conn.get_users(source='test-1')
self.assertEqual(list(users), ['user-id'])
class ProjectTest(DBTestBase,
tests_db.MixinTestsWithBackendScenarios):
def test_get_projects(self):
projects = self.conn.get_projects()
expected = set(['project-id', 'project-id-2', 'project-id-3',
'project-id-4', 'project-id-5', 'project-id-6',
'project-id-7', 'project-id-8'])
self.assertEqual(set(projects), expected)
def test_get_projects_by_source(self):
projects = self.conn.get_projects(source='test-1')
expected = ['project-id']
self.assertEqual(list(projects), expected)
class ResourceTest(DBTestBase,
tests_db.MixinTestsWithBackendScenarios):
@ -664,10 +633,6 @@ class RawSampleTest(DBTestBase,
f = storage.SampleFilter(meter='instance')
results = list(self.conn.get_samples(f))
self.assertEqual(len(results), 5)
results = list(self.conn.get_users())
self.assertEqual(len(results), 5)
results = list(self.conn.get_projects())
self.assertEqual(len(results), 5)
results = list(self.conn.get_resources())
self.assertEqual(len(results), 5)
@ -682,10 +647,6 @@ class RawSampleTest(DBTestBase,
f = storage.SampleFilter(meter='instance')
results = list(self.conn.get_samples(f))
self.assertEqual(len(results), 11)
results = list(self.conn.get_users())
self.assertEqual(len(results), 9)
results = list(self.conn.get_projects())
self.assertEqual(len(results), 8)
results = list(self.conn.get_resources())
self.assertEqual(len(results), 9)
@ -728,12 +689,6 @@ class RawSampleTest(DBTestBase,
f = storage.SampleFilter(meter='instance')
results = list(self.conn.get_samples(f))
self.assertEqual(len(results), 2)
results = list(self.conn.get_users())
self.assertEqual(len(results), 2)
self.assertNotIn('user-id', results)
results = list(self.conn.get_projects())
self.assertEqual(len(results), 2)
self.assertNotIn('project-id', results)
results = list(self.conn.get_resources())
self.assertEqual(len(results), 2)

View File

@ -160,11 +160,6 @@ class BinApiTestCase(base.BaseTestCase):
return r, c
return (None, None)
def test_v1(self):
response, content = self.get_response('v1/meters')
self.assertEqual(200, response.status)
self.assertEqual({'meters': []}, json.loads(content))
def test_v2(self):
response, content = self.get_response('v2/meters')
self.assertEqual(200, response.status)

View File

@ -5,7 +5,4 @@
.. warning::
The V1 API is being deprecated during the Havana development
cycle. Please use the V2 API instead.
.. autoflask:: ceilometer.api.v1.app:app
:undoc-static:
cycle and no longer exists since Juno.

View File

@ -1,3 +0,0 @@
{
"openstack": {}
}

View File

@ -3,7 +3,6 @@ anyjson>=0.3.3
argparse
croniter>=0.3.4 # MIT License
eventlet>=0.13.0
Flask>=0.10,<1.0
happybase>=0.5,!=0.7
iso8601>=0.1.9
jsonpath-rw>=1.2.0,<2.0