Files
aodh/ceilometer/tests/api/v2/test_statistics_scenarios.py
Srinivas Sakhamuri 9f923ae928 Internal error with period overflow
When statistics queried with large period value the overflow
causes error 500. This patch converts the overflow error to
ClientSideError which is returned as 400 bad input error

Change-Id: Iacf89c75428713a151fbe81aa1601df63785f942
Closes-Bug: 1396223
2014-11-25 16:15:58 +00:00

1673 lines
79 KiB
Python

#
# 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 events statistics retrieval."""
import datetime
from ceilometer.publisher import utils
from ceilometer import sample
from ceilometer.tests.api import v2
from ceilometer.tests import db as tests_db
class TestMaxProjectVolume(v2.FunctionalTest,
tests_db.MixinTestsWithBackendScenarios):
PATH = '/meters/volume.size/statistics'
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_json(self.PATH, q=[{'field': 'project_id',
'value': 'project1',
}])
self.assertEqual(7, data[0]['max'])
self.assertEqual(3, data[0]['count'])
def test_start_timestamp(self):
data = self.get_json(self.PATH, q=[{'field': 'project_id',
'value': 'project1',
},
{'field': 'timestamp',
'op': 'ge',
'value': '2012-09-25T11:30:00',
},
])
self.assertEqual(7, data[0]['max'])
self.assertEqual(2, data[0]['count'])
def test_start_timestamp_after(self):
data = self.get_json(self.PATH, q=[{'field': 'project_id',
'value': 'project1',
},
{'field': 'timestamp',
'op': 'ge',
'value': '2012-09-25T12:34:00',
},
])
self.assertEqual([], data)
def test_end_timestamp(self):
data = self.get_json(self.PATH, q=[{'field': 'project_id',
'value': 'project1',
},
{'field': 'timestamp',
'op': 'le',
'value': '2012-09-25T11:30:00',
},
])
self.assertEqual(5, data[0]['max'])
self.assertEqual(1, data[0]['count'])
def test_end_timestamp_before(self):
data = self.get_json(self.PATH, q=[{'field': 'project_id',
'value': 'project1',
},
{'field': 'timestamp',
'op': 'le',
'value': '2012-09-25T09:54:00',
},
])
self.assertEqual([], data)
def test_start_end_timestamp(self):
data = self.get_json(self.PATH, q=[{'field': 'project_id',
'value': 'project1',
},
{'field': 'timestamp',
'op': 'ge',
'value': '2012-09-25T11:30:00',
},
{'field': 'timestamp',
'op': 'le',
'value': '2012-09-25T11:32:00',
},
])
self.assertEqual(6, data[0]['max'])
self.assertEqual(1, data[0]['count'])
class TestMaxResourceVolume(v2.FunctionalTest,
tests_db.MixinTestsWithBackendScenarios):
PATH = '/meters/volume.size/statistics'
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_json(self.PATH, q=[{'field': 'resource_id',
'value': 'resource-id',
}])
self.assertEqual(7, data[0]['max'])
self.assertEqual(3, data[0]['count'])
def test_no_time_bounds_with_period(self):
data = self.get_json(self.PATH,
q=[{'field': 'resource_id',
'value': 'resource-id'}],
period=3600)
self.assertEqual(3, len(data))
self.assertEqual(set([u'2012-09-25T10:30:00',
u'2012-09-25T12:32:00',
u'2012-09-25T11:31:00']),
set(x['duration_start'] for x in data))
self.assertEqual(3600, data[0]['period'])
self.assertEqual(set([u'2012-09-25T10:30:00',
u'2012-09-25T11:30:00',
u'2012-09-25T12:30:00']),
set(x['period_start'] for x in data))
def test_period_with_negative_value(self):
resp = self.get_json(self.PATH, expect_errors=True,
q=[{'field': 'resource_id',
'value': 'resource-id'}],
period=-1)
self.assertEqual(400, resp.status_code)
@tests_db.run_with('mysql', 'hbase', 'db2')
def test_period_with_large_value(self):
resp = self.get_json(self.PATH, expect_errors=True,
q=[{'field': 'user_id',
'value': 'user-id'}],
period=10000000000000)
self.assertEqual(400, resp.status_code)
self.assertIn("Invalid period", resp.body)
def test_start_timestamp(self):
data = self.get_json(self.PATH, q=[{'field': 'resource_id',
'value': 'resource-id',
},
{'field': 'timestamp',
'op': 'ge',
'value': '2012-09-25T11:30:00',
},
])
self.assertEqual(7, data[0]['max'])
self.assertEqual(2, data[0]['count'])
def test_start_timestamp_after(self):
data = self.get_json(self.PATH, q=[{'field': 'resource_id',
'value': 'resource-id',
},
{'field': 'timestamp',
'op': 'ge',
'value': '2012-09-25T12:34:00',
},
])
self.assertEqual([], data)
def test_end_timestamp(self):
data = self.get_json(self.PATH, q=[{'field': 'resource_id',
'value': 'resource-id',
},
{'field': 'timestamp',
'op': 'le',
'value': '2012-09-25T11:30:00',
},
])
self.assertEqual(5, data[0]['max'])
self.assertEqual(1, data[0]['count'])
def test_end_timestamp_before(self):
data = self.get_json(self.PATH, q=[{'field': 'resource_id',
'value': 'resource-id',
},
{'field': 'timestamp',
'op': 'le',
'value': '2012-09-25T09:54:00',
},
])
self.assertEqual([], data)
def test_start_end_timestamp(self):
data = self.get_json(self.PATH, q=[{'field': 'resource_id',
'value': 'resource-id',
},
{'field': 'timestamp',
'op': 'ge',
'value': '2012-09-25T11:30:00',
},
{'field': 'timestamp',
'op': 'le',
'value': '2012-09-25T11:32:00',
},
])
self.assertEqual(6, data[0]['max'])
self.assertEqual(1, data[0]['count'])
class TestSumProjectVolume(v2.FunctionalTest,
tests_db.MixinTestsWithBackendScenarios):
PATH = '/meters/volume.size/statistics'
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_json(self.PATH, q=[{'field': 'project_id',
'value': 'project1',
}])
expected = 5 + 6 + 7
self.assertEqual(expected, data[0]['sum'])
self.assertEqual(3, data[0]['count'])
def test_start_timestamp(self):
data = self.get_json(self.PATH, q=[{'field': 'project_id',
'value': 'project1',
},
{'field': 'timestamp',
'op': 'ge',
'value': '2012-09-25T11:30:00',
},
])
expected = 6 + 7
self.assertEqual(expected, data[0]['sum'])
self.assertEqual(2, data[0]['count'])
def test_start_timestamp_after(self):
data = self.get_json(self.PATH, q=[{'field': 'project_id',
'value': 'project1',
},
{'field': 'timestamp',
'op': 'ge',
'value': '2012-09-25T12:34:00',
},
])
self.assertEqual([], data)
def test_end_timestamp(self):
data = self.get_json(self.PATH, q=[{'field': 'project_id',
'value': 'project1',
},
{'field': 'timestamp',
'op': 'le',
'value': '2012-09-25T11:30:00',
},
])
self.assertEqual(5, data[0]['sum'])
self.assertEqual(1, data[0]['count'])
def test_end_timestamp_before(self):
data = self.get_json(self.PATH, q=[{'field': 'project_id',
'value': 'project1',
},
{'field': 'timestamp',
'op': 'le',
'value': '2012-09-25T09:54:00',
},
])
self.assertEqual([], data)
def test_start_end_timestamp(self):
data = self.get_json(self.PATH, q=[{'field': 'project_id',
'value': 'project1',
},
{'field': 'timestamp',
'op': 'ge',
'value': '2012-09-25T11:30:00',
},
{'field': 'timestamp',
'op': 'le',
'value': '2012-09-25T11:32:00',
},
])
self.assertEqual(6, data[0]['sum'])
self.assertEqual(1, data[0]['count'])
class TestSumResourceVolume(v2.FunctionalTest,
tests_db.MixinTestsWithBackendScenarios):
PATH = '/meters/volume.size/statistics'
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_json(self.PATH, q=[{'field': 'resource_id',
'value': 'resource-id',
}])
self.assertEqual(5 + 6 + 7, data[0]['sum'])
self.assertEqual(3, data[0]['count'])
def test_no_time_bounds_with_period(self):
data = self.get_json(self.PATH,
q=[{'field': 'resource_id',
'value': 'resource-id'}],
period=1800)
self.assertEqual(3, len(data))
self.assertEqual(set([u'2012-09-25T10:30:00',
u'2012-09-25T12:32:00',
u'2012-09-25T11:31:00']),
set(x['duration_start'] for x in data))
self.assertEqual(1800, data[0]['period'])
self.assertEqual(set([u'2012-09-25T10:30:00',
u'2012-09-25T11:30:00',
u'2012-09-25T12:30:00']),
set(x['period_start'] for x in data))
def test_start_timestamp(self):
data = self.get_json(self.PATH, q=[{'field': 'resource_id',
'value': 'resource-id',
},
{'field': 'timestamp',
'op': 'ge',
'value': '2012-09-25T11:30:00',
}])
self.assertEqual(6 + 7, data[0]['sum'])
self.assertEqual(2, data[0]['count'])
def test_start_timestamp_with_period(self):
data = self.get_json(self.PATH,
q=[{'field': 'resource_id',
'value': 'resource-id'},
{'field': 'timestamp',
'op': 'ge',
'value': '2012-09-25T10:15:00'}],
period=7200)
self.assertEqual(2, len(data))
self.assertEqual(set([u'2012-09-25T10:30:00',
u'2012-09-25T12:32:00']),
set(x['duration_start'] for x in data))
self.assertEqual(7200, data[0]['period'])
self.assertEqual(set([u'2012-09-25T10:15:00',
u'2012-09-25T12:15:00']),
set(x['period_start'] for x in data))
def test_start_timestamp_after(self):
data = self.get_json(self.PATH, q=[{'field': 'resource_id',
'value': 'resource-id',
},
{'field': 'timestamp',
'op': 'ge',
'value': '2012-09-25T12:34:00',
}])
self.assertEqual([], data)
def test_end_timestamp(self):
data = self.get_json(self.PATH, q=[{'field': 'resource_id',
'value': 'resource-id',
},
{'field': 'timestamp',
'op': 'le',
'value': '2012-09-25T11:30:00',
}])
self.assertEqual(5, data[0]['sum'])
self.assertEqual(1, data[0]['count'])
def test_end_timestamp_before(self):
data = self.get_json(self.PATH, q=[{'field': 'resource_id',
'value': 'resource-id',
},
{'field': 'timestamp',
'op': 'le',
'value': '2012-09-25T09:54:00',
}])
self.assertEqual([], data)
def test_start_end_timestamp(self):
data = self.get_json(self.PATH, q=[{'field': 'resource_id',
'value': 'resource-id',
},
{'field': 'timestamp',
'op': 'ge',
'value': '2012-09-25T11:30:00',
},
{'field': 'timestamp',
'op': 'lt',
'value': '2012-09-25T11:32:00',
}])
self.assertEqual(6, data[0]['sum'])
self.assertEqual(1, data[0]['count'])
class TestGroupByInstance(v2.FunctionalTest,
tests_db.MixinTestsWithBackendScenarios):
PATH = '/meters/instance/statistics'
def setUp(self):
super(TestGroupByInstance, self).setUp()
test_sample_data = (
{'volume': 2, 'user': 'user-1', 'project': 'project-1',
'resource': 'resource-1', 'timestamp': (2013, 8, 1, 16, 10),
'metadata_flavor': 'm1.tiny', 'metadata_event': 'event-1',
'source': 'source-2'},
{'volume': 2, 'user': 'user-1', 'project': 'project-2',
'resource': 'resource-1', 'timestamp': (2013, 8, 1, 15, 37),
'metadata_flavor': 'm1.large', 'metadata_event': 'event-1',
'source': 'source-2'},
{'volume': 1, 'user': 'user-2', 'project': 'project-1',
'resource': 'resource-2', 'timestamp': (2013, 8, 1, 10, 11),
'metadata_flavor': 'm1.tiny', 'metadata_event': 'event-2',
'source': 'source-1'},
{'volume': 1, 'user': 'user-2', 'project': 'project-1',
'resource': 'resource-2', 'timestamp': (2013, 8, 1, 10, 40),
'metadata_flavor': 'm1.large', 'metadata_event': 'event-2',
'source': 'source-1'},
{'volume': 2, 'user': 'user-2', 'project': 'project-1',
'resource': 'resource-1', 'timestamp': (2013, 8, 1, 14, 59),
'metadata_flavor': 'm1.large', 'metadata_event': 'event-2',
'source': 'source-1'},
{'volume': 4, 'user': 'user-2', 'project': 'project-2',
'resource': 'resource-2', 'timestamp': (2013, 8, 1, 17, 28),
'metadata_flavor': 'm1.large', 'metadata_event': 'event-2',
'source': 'source-1'},
{'volume': 4, 'user': 'user-3', 'project': 'project-1',
'resource': 'resource-3', 'timestamp': (2013, 8, 1, 11, 22),
'metadata_flavor': 'm1.tiny', 'metadata_event': 'event-2',
'source': 'source-3'},
)
for test_sample in test_sample_data:
c = sample.Sample(
'instance',
sample.TYPE_CUMULATIVE,
unit='s',
volume=test_sample['volume'],
user_id=test_sample['user'],
project_id=test_sample['project'],
resource_id=test_sample['resource'],
timestamp=datetime.datetime(*test_sample['timestamp']),
resource_metadata={'flavor': test_sample['metadata_flavor'],
'event': test_sample['metadata_event'], },
source=test_sample['source'],
)
msg = utils.meter_message_from_counter(
c,
self.CONF.publisher.metering_secret,
)
self.conn.record_metering_data(msg)
def test_group_by_user(self):
data = self.get_json(self.PATH, groupby=['user_id'])
groupby_keys_set = set(x for sub_dict in data
for x in sub_dict['groupby'].keys())
groupby_vals_set = set(x for sub_dict in data
for x in sub_dict['groupby'].values())
self.assertEqual(set(['user_id']), groupby_keys_set)
self.assertEqual(set(['user-1', 'user-2', 'user-3']), groupby_vals_set)
for r in data:
grp = r['groupby']
if grp == {'user_id': 'user-1'}:
self.assertEqual(2, r['count'])
self.assertEqual('s', r['unit'])
self.assertEqual(2, r['min'])
self.assertEqual(2, r['max'])
self.assertEqual(4, r['sum'])
self.assertEqual(2, r['avg'])
elif grp == {'user_id': 'user-2'}:
self.assertEqual(4, r['count'])
self.assertEqual('s', r['unit'])
self.assertEqual(1, r['min'])
self.assertEqual(4, r['max'])
self.assertEqual(8, r['sum'])
self.assertEqual(2, r['avg'])
elif grp == {'user_id': 'user-3'}:
self.assertEqual(1, r['count'])
self.assertEqual('s', r['unit'])
self.assertEqual(4, r['min'])
self.assertEqual(4, r['max'])
self.assertEqual(4, r['sum'])
self.assertEqual(4, r['avg'])
def test_group_by_resource(self):
data = self.get_json(self.PATH, groupby=['resource_id'])
groupby_keys_set = set(x for sub_dict in data
for x in sub_dict['groupby'].keys())
groupby_vals_set = set(x for sub_dict in data
for x in sub_dict['groupby'].values())
self.assertEqual(set(['resource_id']), groupby_keys_set)
self.assertEqual(set(['resource-1', 'resource-2', 'resource-3']),
groupby_vals_set)
for r in data:
grp = r['groupby']
if grp == {'resource_id': 'resource-1'}:
self.assertEqual(3, r['count'])
self.assertEqual('s', r['unit'])
self.assertEqual(2, r['min'])
self.assertEqual(2, r['max'])
self.assertEqual(6, r['sum'])
self.assertEqual(2, r['avg'])
elif grp == {'resource_id': 'resource-2'}:
self.assertEqual(3, r['count'])
self.assertEqual('s', r['unit'])
self.assertEqual(1, r['min'])
self.assertEqual(4, r['max'])
self.assertEqual(6, r['sum'])
self.assertEqual(2, r['avg'])
elif grp == {'resource_id': 'resource-3'}:
self.assertEqual(1, r['count'])
self.assertEqual('s', r['unit'])
self.assertEqual(4, r['min'])
self.assertEqual(4, r['max'])
self.assertEqual(4, r['sum'])
self.assertEqual(4, r['avg'])
def test_group_by_project(self):
data = self.get_json(self.PATH, groupby=['project_id'])
groupby_keys_set = set(x for sub_dict in data
for x in sub_dict['groupby'].keys())
groupby_vals_set = set(x for sub_dict in data
for x in sub_dict['groupby'].values())
self.assertEqual(set(['project_id']), groupby_keys_set)
self.assertEqual(set(['project-1', 'project-2']), groupby_vals_set)
for r in data:
grp = r['groupby']
if grp == {'project_id': 'project-1'}:
self.assertEqual(5, r['count'])
self.assertEqual('s', r['unit'])
self.assertEqual(1, r['min'])
self.assertEqual(4, r['max'])
self.assertEqual(10, r['sum'])
self.assertEqual(2, r['avg'])
elif grp == {'project_id': 'project-2'}:
self.assertEqual(2, r['count'])
self.assertEqual('s', r['unit'])
self.assertEqual(2, r['min'])
self.assertEqual(4, r['max'])
self.assertEqual(6, r['sum'])
self.assertEqual(3, r['avg'])
def test_group_by_unknown_field(self):
response = self.get_json(self.PATH,
expect_errors=True,
groupby=['wtf'])
self.assertEqual(400, response.status_code)
def test_group_by_multiple_regular(self):
data = self.get_json(self.PATH, groupby=['user_id', 'resource_id'])
groupby_keys_set = set(x for sub_dict in data
for x in sub_dict['groupby'].keys())
groupby_vals_set = set(x for sub_dict in data
for x in sub_dict['groupby'].values())
self.assertEqual(set(['user_id', 'resource_id']), groupby_keys_set)
self.assertEqual(set(['user-1', 'user-2', 'user-3', 'resource-1',
'resource-2', 'resource-3']),
groupby_vals_set)
for r in data:
grp = r['groupby']
if grp == {'user_id': 'user-1',
'resource_id': 'resource-1'}:
self.assertEqual(2, r['count'])
self.assertEqual('s', r['unit'])
self.assertEqual(2, r['min'])
self.assertEqual(2, r['max'])
self.assertEqual(4, r['sum'])
self.assertEqual(2, r['avg'])
elif grp == {'user_id': 'user-2',
'resource_id': 'resource-1'}:
self.assertEqual(1, r['count'])
self.assertEqual('s', r['unit'])
self.assertEqual(2, r['min'])
self.assertEqual(2, r['max'])
self.assertEqual(2, r['sum'])
self.assertEqual(2, r['avg'])
elif grp == {'user_id': 'user-2',
'resource_id': 'resource-2'}:
self.assertEqual(3, r['count'])
self.assertEqual('s', r['unit'])
self.assertEqual(1, r['min'])
self.assertEqual(4, r['max'])
self.assertEqual(6, r['sum'])
self.assertEqual(2, r['avg'])
elif grp == {'user_id': 'user-3',
'resource_id': 'resource-3'}:
self.assertEqual(1, r['count'])
self.assertEqual('s', r['unit'])
self.assertEqual(4, r['min'])
self.assertEqual(4, r['max'])
self.assertEqual(4, r['sum'])
self.assertEqual(4, r['avg'])
else:
self.assertNotEqual(grp, {'user_id': 'user-1',
'resource_id': 'resource-2'})
self.assertNotEqual(grp, {'user_id': 'user-1',
'resource_id': 'resource-3'})
self.assertNotEqual(grp, {'user_id': 'user-2',
'resource_id': 'resource-3'})
self.assertNotEqual(grp, {'user_id': 'user-3',
'resource_id': 'resource-1'})
self.assertNotEqual(grp, {'user_id': 'user-3',
'resource_id': 'resource-2'})
def test_group_by_with_query_filter(self):
data = self.get_json(self.PATH,
q=[{'field': 'project_id',
'op': 'eq',
'value': 'project-1'}],
groupby=['resource_id'])
groupby_keys_set = set(x for sub_dict in data
for x in sub_dict['groupby'].keys())
groupby_vals_set = set(x for sub_dict in data
for x in sub_dict['groupby'].values())
self.assertEqual(set(['resource_id']), groupby_keys_set)
self.assertEqual(set(['resource-1', 'resource-2', 'resource-3']),
groupby_vals_set)
for r in data:
grp = r['groupby']
if grp == {'resource_id': 'resource-1'}:
self.assertEqual(2, r['count'])
self.assertEqual('s', r['unit'])
self.assertEqual(2, r['min'])
self.assertEqual(2, r['max'])
self.assertEqual(4, r['sum'])
self.assertEqual(2, r['avg'])
elif grp == {'resource_id': 'resource-2'}:
self.assertEqual(2, r['count'])
self.assertEqual('s', r['unit'])
self.assertEqual(1, r['min'])
self.assertEqual(1, r['max'])
self.assertEqual(2, r['sum'])
self.assertEqual(1, r['avg'])
elif grp == {'resource_id': 'resource-3'}:
self.assertEqual(1, r['count'])
self.assertEqual('s', r['unit'])
self.assertEqual(4, r['min'])
self.assertEqual(4, r['max'])
self.assertEqual(4, r['sum'])
self.assertEqual(4, r['avg'])
def test_group_by_with_query_filter_multiple(self):
data = self.get_json(self.PATH,
q=[{'field': 'user_id',
'op': 'eq',
'value': 'user-2'},
{'field': 'source',
'op': 'eq',
'value': 'source-1'}],
groupby=['project_id', 'resource_id'])
groupby_keys_set = set(x for sub_dict in data
for x in sub_dict['groupby'].keys())
groupby_vals_set = set(x for sub_dict in data
for x in sub_dict['groupby'].values())
self.assertEqual(set(['project_id', 'resource_id']), groupby_keys_set)
self.assertEqual(set(['project-1', 'project-2',
'resource-1', 'resource-2']),
groupby_vals_set)
for r in data:
grp = r['groupby']
if grp == {'project_id': 'project-1',
'resource_id': 'resource-1'}:
self.assertEqual(1, r['count'])
self.assertEqual('s', r['unit'])
self.assertEqual(2, r['min'])
self.assertEqual(2, r['max'])
self.assertEqual(2, r['sum'])
self.assertEqual(2, r['avg'])
elif grp == {'project_id': 'project-1',
'resource_id': 'resource-2'}:
self.assertEqual(2, r['count'])
self.assertEqual('s', r['unit'])
self.assertEqual(1, r['min'])
self.assertEqual(1, r['max'])
self.assertEqual(2, r['sum'])
self.assertEqual(1, r['avg'])
elif grp == {'project_id': 'project-2',
'resource_id': 'resource-2'}:
self.assertEqual(1, r['count'])
self.assertEqual('s', r['unit'])
self.assertEqual(4, r['min'])
self.assertEqual(4, r['max'])
self.assertEqual(4, r['sum'])
self.assertEqual(4, r['avg'])
else:
self.assertNotEqual(grp, {'project_id': 'project-2',
'resource_id': 'resource-1'})
def test_group_by_with_period(self):
data = self.get_json(self.PATH,
groupby=['project_id'],
period=7200)
groupby_keys_set = set(x for sub_dict in data
for x in sub_dict['groupby'].keys())
groupby_vals_set = set(x for sub_dict in data
for x in sub_dict['groupby'].values())
self.assertEqual(set(['project_id']), groupby_keys_set)
self.assertEqual(set(['project-1', 'project-2']), groupby_vals_set)
period_start_set = set(sub_dict['period_start'] for sub_dict in data)
period_start_valid = set([u'2013-08-01T10:11:00',
u'2013-08-01T14:11:00',
u'2013-08-01T16:11:00'])
self.assertEqual(period_start_valid, period_start_set)
for r in data:
grp = r['groupby']
period_start = r['period_start']
if (grp == {'project_id': 'project-1'} and
period_start == u'2013-08-01T10:11:00'):
self.assertEqual(3, r['count'])
self.assertEqual('s', r['unit'])
self.assertEqual(1, r['min'])
self.assertEqual(4, r['max'])
self.assertEqual(6, r['sum'])
self.assertEqual(2, r['avg'])
self.assertEqual(4260, r['duration'])
self.assertEqual(u'2013-08-01T10:11:00', r['duration_start'])
self.assertEqual(u'2013-08-01T11:22:00', r['duration_end'])
self.assertEqual(7200, r['period'])
self.assertEqual(u'2013-08-01T12:11:00', r['period_end'])
elif (grp == {'project_id': 'project-1'} and
period_start == u'2013-08-01T14:11:00'):
self.assertEqual(2, r['count'])
self.assertEqual('s', r['unit'])
self.assertEqual(2, r['min'])
self.assertEqual(2, r['max'])
self.assertEqual(4, r['sum'])
self.assertEqual(2, r['avg'])
self.assertEqual(4260, r['duration'])
self.assertEqual(u'2013-08-01T14:59:00', r['duration_start'])
self.assertEqual(u'2013-08-01T16:10:00', r['duration_end'])
self.assertEqual(7200, r['period'])
self.assertEqual(u'2013-08-01T16:11:00', r['period_end'])
elif (grp == {'project_id': 'project-2'} and
period_start == u'2013-08-01T14:11:00'):
self.assertEqual(1, r['count'])
self.assertEqual('s', r['unit'])
self.assertEqual(2, r['min'])
self.assertEqual(2, r['max'])
self.assertEqual(2, r['sum'])
self.assertEqual(2, r['avg'])
self.assertEqual(0, r['duration'])
self.assertEqual(u'2013-08-01T15:37:00', r['duration_start'])
self.assertEqual(u'2013-08-01T15:37:00', r['duration_end'])
self.assertEqual(7200, r['period'])
self.assertEqual(u'2013-08-01T16:11:00', r['period_end'])
elif (grp == {'project_id': 'project-2'} and
period_start == u'2013-08-01T16:11:00'):
self.assertEqual(1, r['count'])
self.assertEqual('s', r['unit'])
self.assertEqual(4, r['min'])
self.assertEqual(4, r['max'])
self.assertEqual(4, r['sum'])
self.assertEqual(4, r['avg'])
self.assertEqual(0, r['duration'])
self.assertEqual(u'2013-08-01T17:28:00', r['duration_start'])
self.assertEqual(u'2013-08-01T17:28:00', r['duration_end'])
self.assertEqual(7200, r['period'])
self.assertEqual(u'2013-08-01T18:11:00', r['period_end'])
else:
self.assertNotEqual([grp, period_start],
[{'project_id': 'project-1'},
u'2013-08-01T16:11:00'])
self.assertNotEqual([grp, period_start],
[{'project_id': 'project-2'},
u'2013-08-01T10:11:00'])
def test_group_by_with_query_filter_and_period(self):
data = self.get_json(self.PATH,
q=[{'field': 'source',
'op': 'eq',
'value': 'source-1'}],
groupby=['project_id'],
period=7200)
groupby_keys_set = set(x for sub_dict in data
for x in sub_dict['groupby'].keys())
groupby_vals_set = set(x for sub_dict in data
for x in sub_dict['groupby'].values())
self.assertEqual(set(['project_id']), groupby_keys_set)
self.assertEqual(set(['project-1', 'project-2']), groupby_vals_set)
period_start_set = set(sub_dict['period_start'] for sub_dict in data)
period_start_valid = set([u'2013-08-01T10:11:00',
u'2013-08-01T14:11:00',
u'2013-08-01T16:11:00'])
self.assertEqual(period_start_valid, period_start_set)
for r in data:
grp = r['groupby']
period_start = r['period_start']
if (grp == {'project_id': 'project-1'} and
period_start == u'2013-08-01T10:11:00'):
self.assertEqual(2, r['count'])
self.assertEqual('s', r['unit'])
self.assertEqual(1, r['min'])
self.assertEqual(1, r['max'])
self.assertEqual(2, r['sum'])
self.assertEqual(1, r['avg'])
self.assertEqual(1740, r['duration'])
self.assertEqual(u'2013-08-01T10:11:00', r['duration_start'])
self.assertEqual(u'2013-08-01T10:40:00', r['duration_end'])
self.assertEqual(7200, r['period'])
self.assertEqual(u'2013-08-01T12:11:00', r['period_end'])
elif (grp == {'project_id': 'project-1'} and
period_start == u'2013-08-01T14:11:00'):
self.assertEqual(1, r['count'])
self.assertEqual('s', r['unit'])
self.assertEqual(2, r['min'])
self.assertEqual(2, r['max'])
self.assertEqual(2, r['sum'])
self.assertEqual(2, r['avg'])
self.assertEqual(0, r['duration'])
self.assertEqual(u'2013-08-01T14:59:00', r['duration_start'])
self.assertEqual(u'2013-08-01T14:59:00', r['duration_end'])
self.assertEqual(7200, r['period'])
self.assertEqual(u'2013-08-01T16:11:00', r['period_end'])
elif (grp == {'project_id': 'project-2'} and
period_start == u'2013-08-01T16:11:00'):
self.assertEqual(1, r['count'])
self.assertEqual('s', r['unit'])
self.assertEqual(4, r['min'])
self.assertEqual(4, r['max'])
self.assertEqual(4, r['sum'])
self.assertEqual(4, r['avg'])
self.assertEqual(0, r['duration'])
self.assertEqual(u'2013-08-01T17:28:00', r['duration_start'])
self.assertEqual(u'2013-08-01T17:28:00', r['duration_end'])
self.assertEqual(7200, r['period'])
self.assertEqual(u'2013-08-01T18:11:00', r['period_end'])
else:
self.assertNotEqual([grp, period_start],
[{'project_id': 'project-1'},
u'2013-08-01T16:11:00'])
self.assertNotEqual([grp, period_start],
[{'project_id': 'project-2'},
u'2013-08-01T10:11:00'])
self.assertNotEqual([grp, period_start],
[{'project_id': 'project-2'},
u'2013-08-01T14:11:00'])
def test_group_by_start_timestamp_after(self):
data = self.get_json(self.PATH,
q=[{'field': 'timestamp',
'op': 'ge',
'value': '2013-08-01T17:28:01'}],
groupby=['project_id'])
self.assertEqual([], data)
def test_group_by_end_timestamp_before(self):
data = self.get_json(self.PATH,
q=[{'field': 'timestamp',
'op': 'le',
'value': '2013-08-01T10:10:59'}],
groupby=['project_id'])
self.assertEqual([], data)
def test_group_by_start_timestamp(self):
data = self.get_json(self.PATH,
q=[{'field': 'timestamp',
'op': 'ge',
'value': '2013-08-01T14:58:00'}],
groupby=['project_id'])
groupby_keys_set = set(x for sub_dict in data
for x in sub_dict['groupby'].keys())
groupby_vals_set = set(x for sub_dict in data
for x in sub_dict['groupby'].values())
self.assertEqual(set(['project_id']), groupby_keys_set)
self.assertEqual(set(['project-1', 'project-2']), groupby_vals_set)
for r in data:
grp = r['groupby']
if grp == {'project_id': 'project-1'}:
self.assertEqual(2, r['count'])
self.assertEqual('s', r['unit'])
self.assertEqual(2, r['min'])
self.assertEqual(2, r['max'])
self.assertEqual(4, r['sum'])
self.assertEqual(2, r['avg'])
elif grp == {'project_id': 'project-2'}:
self.assertEqual(2, r['count'])
self.assertEqual('s', r['unit'])
self.assertEqual(2, r['min'])
self.assertEqual(4, r['max'])
self.assertEqual(6, r['sum'])
self.assertEqual(3, r['avg'])
def test_group_by_end_timestamp(self):
data = self.get_json(self.PATH,
q=[{'field': 'timestamp',
'op': 'le',
'value': '2013-08-01T11:45:00'}],
groupby=['project_id'])
groupby_keys_set = set(x for sub_dict in data
for x in sub_dict['groupby'].keys())
groupby_vals_set = set(x for sub_dict in data
for x in sub_dict['groupby'].values())
self.assertEqual(set(['project_id']), groupby_keys_set)
self.assertEqual(set(['project-1']), groupby_vals_set)
for r in data:
grp = r['groupby']
if grp == {'project_id': 'project-1'}:
self.assertEqual(3, r['count'])
self.assertEqual('s', r['unit'])
self.assertEqual(1, r['min'])
self.assertEqual(4, r['max'])
self.assertEqual(6, r['sum'])
self.assertEqual(2, r['avg'])
def test_group_by_start_end_timestamp(self):
data = self.get_json(self.PATH,
q=[{'field': 'timestamp',
'op': 'ge',
'value': '2013-08-01T08:17:03'},
{'field': 'timestamp',
'op': 'le',
'value': '2013-08-01T23:59:59'}],
groupby=['project_id'])
groupby_keys_set = set(x for sub_dict in data
for x in sub_dict['groupby'].keys())
groupby_vals_set = set(x for sub_dict in data
for x in sub_dict['groupby'].values())
self.assertEqual(set(['project_id']), groupby_keys_set)
self.assertEqual(set(['project-1', 'project-2']), groupby_vals_set)
for r in data:
grp = r['groupby']
if grp == {'project_id': 'project-1'}:
self.assertEqual(5, r['count'])
self.assertEqual('s', r['unit'])
self.assertEqual(1, r['min'])
self.assertEqual(4, r['max'])
self.assertEqual(10, r['sum'])
self.assertEqual(2, r['avg'])
elif grp == {'project_id': 'project-2'}:
self.assertEqual(2, r['count'])
self.assertEqual('s', r['unit'])
self.assertEqual(2, r['min'])
self.assertEqual(4, r['max'])
self.assertEqual(6, r['sum'])
self.assertEqual(3, r['avg'])
def test_group_by_start_end_timestamp_with_query_filter(self):
data = self.get_json(self.PATH,
q=[{'field': 'project_id',
'op': 'eq',
'value': 'project-1'},
{'field': 'timestamp',
'op': 'ge',
'value': '2013-08-01T11:01:00'},
{'field': 'timestamp',
'op': 'le',
'value': '2013-08-01T20:00:00'}],
groupby=['resource_id'])
groupby_keys_set = set(x for sub_dict in data
for x in sub_dict['groupby'].keys())
groupby_vals_set = set(x for sub_dict in data
for x in sub_dict['groupby'].values())
self.assertEqual(set(['resource_id']), groupby_keys_set)
self.assertEqual(set(['resource-1', 'resource-3']), groupby_vals_set)
for r in data:
grp = r['groupby']
if grp == {'resource_id': 'resource-1'}:
self.assertEqual(2, r['count'])
self.assertEqual('s', r['unit'])
self.assertEqual(2, r['min'])
self.assertEqual(2, r['max'])
self.assertEqual(4, r['sum'])
self.assertEqual(2, r['avg'])
elif grp == {'resource_id': 'resource-3'}:
self.assertEqual(1, r['count'])
self.assertEqual('s', r['unit'])
self.assertEqual(4, r['min'])
self.assertEqual(4, r['max'])
self.assertEqual(4, r['sum'])
self.assertEqual(4, r['avg'])
def test_group_by_start_end_timestamp_with_period(self):
data = self.get_json(self.PATH,
q=[{'field': 'timestamp',
'op': 'ge',
'value': '2013-08-01T14:00:00'},
{'field': 'timestamp',
'op': 'le',
'value': '2013-08-01T17:00:00'}],
groupby=['project_id'],
period=3600)
groupby_keys_set = set(x for sub_dict in data
for x in sub_dict['groupby'].keys())
groupby_vals_set = set(x for sub_dict in data
for x in sub_dict['groupby'].values())
self.assertEqual(set(['project_id']), groupby_keys_set)
self.assertEqual(set(['project-1', 'project-2']), groupby_vals_set)
period_start_set = set(sub_dict['period_start'] for sub_dict in data)
period_start_valid = set([u'2013-08-01T14:00:00',
u'2013-08-01T15:00:00',
u'2013-08-01T16:00:00'])
self.assertEqual(period_start_valid, period_start_set)
for r in data:
grp = r['groupby']
period_start = r['period_start']
if (grp == {'project_id': 'project-1'} and
period_start == u'2013-08-01T14:00:00'):
self.assertEqual(1, r['count'])
self.assertEqual('s', r['unit'])
self.assertEqual(2, r['min'])
self.assertEqual(2, r['max'])
self.assertEqual(2, r['sum'])
self.assertEqual(2, r['avg'])
self.assertEqual(0, r['duration'])
self.assertEqual(u'2013-08-01T14:59:00', r['duration_start'])
self.assertEqual(u'2013-08-01T14:59:00', r['duration_end'])
self.assertEqual(3600, r['period'])
self.assertEqual(u'2013-08-01T15:00:00', r['period_end'])
elif (grp == {'project_id': 'project-1'} and
period_start == u'2013-08-01T16:00:00'):
self.assertEqual(1, r['count'])
self.assertEqual('s', r['unit'])
self.assertEqual(2, r['min'])
self.assertEqual(2, r['max'])
self.assertEqual(2, r['sum'])
self.assertEqual(2, r['avg'])
self.assertEqual(0, r['duration'])
self.assertEqual(u'2013-08-01T16:10:00', r['duration_start'])
self.assertEqual(u'2013-08-01T16:10:00', r['duration_end'])
self.assertEqual(3600, r['period'])
self.assertEqual(u'2013-08-01T17:00:00', r['period_end'])
elif (grp == {'project_id': 'project-2'} and
period_start == u'2013-08-01T15:00:00'):
self.assertEqual(1, r['count'])
self.assertEqual('s', r['unit'])
self.assertEqual(2, r['min'])
self.assertEqual(2, r['max'])
self.assertEqual(2, r['sum'])
self.assertEqual(2, r['avg'])
self.assertEqual(0, r['duration'])
self.assertEqual(u'2013-08-01T15:37:00', r['duration_start'])
self.assertEqual(u'2013-08-01T15:37:00', r['duration_end'])
self.assertEqual(3600, r['period'])
self.assertEqual(u'2013-08-01T16:00:00', r['period_end'])
else:
self.assertNotEqual([grp, period_start],
[{'project_id': 'project-1'},
u'2013-08-01T15:00:00'])
self.assertNotEqual([grp, period_start],
[{'project_id': 'project-2'},
u'2013-08-01T14:00:00'])
self.assertNotEqual([grp, period_start],
[{'project_id': 'project-2'},
u'2013-08-01T16:00:00'])
def test_group_by_start_end_timestamp_with_query_filter_and_period(self):
data = self.get_json(self.PATH,
q=[{'field': 'source',
'op': 'eq',
'value': 'source-1'},
{'field': 'timestamp',
'op': 'ge',
'value': '2013-08-01T10:00:00'},
{'field': 'timestamp',
'op': 'le',
'value': '2013-08-01T18:00:00'}],
groupby=['project_id'],
period=7200)
groupby_keys_set = set(x for sub_dict in data
for x in sub_dict['groupby'].keys())
groupby_vals_set = set(x for sub_dict in data
for x in sub_dict['groupby'].values())
self.assertEqual(set(['project_id']), groupby_keys_set)
self.assertEqual(set(['project-1', 'project-2']), groupby_vals_set)
period_start_set = set(sub_dict['period_start'] for sub_dict in data)
period_start_valid = set([u'2013-08-01T10:00:00',
u'2013-08-01T14:00:00',
u'2013-08-01T16:00:00'])
self.assertEqual(period_start_valid, period_start_set)
for r in data:
grp = r['groupby']
period_start = r['period_start']
if (grp == {'project_id': 'project-1'} and
period_start == u'2013-08-01T10:00:00'):
self.assertEqual(2, r['count'])
self.assertEqual('s', r['unit'])
self.assertEqual(1, r['min'])
self.assertEqual(1, r['max'])
self.assertEqual(2, r['sum'])
self.assertEqual(1, r['avg'])
self.assertEqual(1740, r['duration'])
self.assertEqual(u'2013-08-01T10:11:00', r['duration_start'])
self.assertEqual(u'2013-08-01T10:40:00', r['duration_end'])
self.assertEqual(7200, r['period'])
self.assertEqual(u'2013-08-01T12:00:00', r['period_end'])
elif (grp == {'project_id': 'project-1'} and
period_start == u'2013-08-01T14:00:00'):
self.assertEqual(1, r['count'])
self.assertEqual('s', r['unit'])
self.assertEqual(2, r['min'])
self.assertEqual(2, r['max'])
self.assertEqual(2, r['sum'])
self.assertEqual(2, r['avg'])
self.assertEqual(0, r['duration'])
self.assertEqual(u'2013-08-01T14:59:00', r['duration_start'])
self.assertEqual(u'2013-08-01T14:59:00', r['duration_end'])
self.assertEqual(7200, r['period'])
self.assertEqual(u'2013-08-01T16:00:00', r['period_end'])
elif (grp == {'project_id': 'project-2'} and
period_start == u'2013-08-01T16:00:00'):
self.assertEqual(1, r['count'])
self.assertEqual('s', r['unit'])
self.assertEqual(4, r['min'])
self.assertEqual(4, r['max'])
self.assertEqual(4, r['sum'])
self.assertEqual(4, r['avg'])
self.assertEqual(0, r['duration'])
self.assertEqual(u'2013-08-01T17:28:00', r['duration_start'])
self.assertEqual(u'2013-08-01T17:28:00', r['duration_end'])
self.assertEqual(7200, r['period'])
self.assertEqual(u'2013-08-01T18:00:00', r['period_end'])
else:
self.assertNotEqual([grp, period_start],
[{'project_id': 'project-1'},
u'2013-08-01T16:00:00'])
self.assertNotEqual([grp, period_start],
[{'project_id': 'project-2'},
u'2013-08-01T10:00:00'])
self.assertNotEqual([grp, period_start],
[{'project_id': 'project-2'},
u'2013-08-01T14:00:00'])
@tests_db.run_with('mongodb', 'hbase', 'db2')
class TestGroupBySource(v2.FunctionalTest,
tests_db.MixinTestsWithBackendScenarios):
# FIXME(terriyu): We have to put test_group_by_source in its own class
# because SQLAlchemy currently doesn't support group by source statistics.
# When group by source is supported in SQLAlchemy, this test should be
# moved to TestGroupByInstance with all the other group by statistics
# tests.
PATH = '/meters/instance/statistics'
def setUp(self):
super(TestGroupBySource, self).setUp()
test_sample_data = (
{'volume': 2, 'user': 'user-1', 'project': 'project-1',
'resource': 'resource-1', 'timestamp': (2013, 8, 1, 16, 10),
'metadata_flavor': 'm1.tiny', 'metadata_event': 'event-1',
'source': 'source-2'},
{'volume': 2, 'user': 'user-1', 'project': 'project-2',
'resource': 'resource-1', 'timestamp': (2013, 8, 1, 15, 37),
'metadata_flavor': 'm1.large', 'metadata_event': 'event-1',
'source': 'source-2'},
{'volume': 1, 'user': 'user-2', 'project': 'project-1',
'resource': 'resource-2', 'timestamp': (2013, 8, 1, 10, 11),
'metadata_flavor': 'm1.tiny', 'metadata_event': 'event-2',
'source': 'source-1'},
{'volume': 1, 'user': 'user-2', 'project': 'project-1',
'resource': 'resource-2', 'timestamp': (2013, 8, 1, 10, 40),
'metadata_flavor': 'm1.large', 'metadata_event': 'event-2',
'source': 'source-1'},
{'volume': 2, 'user': 'user-2', 'project': 'project-1',
'resource': 'resource-1', 'timestamp': (2013, 8, 1, 14, 59),
'metadata_flavor': 'm1.large', 'metadata_event': 'event-2',
'source': 'source-1'},
{'volume': 4, 'user': 'user-2', 'project': 'project-2',
'resource': 'resource-2', 'timestamp': (2013, 8, 1, 17, 28),
'metadata_flavor': 'm1.large', 'metadata_event': 'event-2',
'source': 'source-1'},
{'volume': 4, 'user': 'user-3', 'project': 'project-1',
'resource': 'resource-3', 'timestamp': (2013, 8, 1, 11, 22),
'metadata_flavor': 'm1.tiny', 'metadata_event': 'event-2',
'source': 'source-3'},
)
for test_sample in test_sample_data:
c = sample.Sample(
'instance',
sample.TYPE_CUMULATIVE,
unit='s',
volume=test_sample['volume'],
user_id=test_sample['user'],
project_id=test_sample['project'],
resource_id=test_sample['resource'],
timestamp=datetime.datetime(*test_sample['timestamp']),
resource_metadata={'flavor': test_sample['metadata_flavor'],
'event': test_sample['metadata_event'], },
source=test_sample['source'],
)
msg = utils.meter_message_from_counter(
c,
self.CONF.publisher.metering_secret,
)
self.conn.record_metering_data(msg)
def tearDown(self):
self.conn.clear()
super(TestGroupBySource, self).tearDown()
def test_group_by_source(self):
data = self.get_json(self.PATH, groupby=['source'])
groupby_keys_set = set(x for sub_dict in data
for x in sub_dict['groupby'].keys())
groupby_vals_set = set(x for sub_dict in data
for x in sub_dict['groupby'].values())
self.assertEqual(set(['source']), groupby_keys_set)
self.assertEqual(set(['source-1', 'source-2', 'source-3']),
groupby_vals_set)
for r in data:
grp = r['groupby']
if grp == {'source': 'source-1'}:
self.assertEqual(4, r['count'])
self.assertEqual('s', r['unit'])
self.assertEqual(1, r['min'])
self.assertEqual(4, r['max'])
self.assertEqual(8, r['sum'])
self.assertEqual(2, r['avg'])
elif grp == {'source': 'source-2'}:
self.assertEqual(2, r['count'])
self.assertEqual('s', r['unit'])
self.assertEqual(2, r['min'])
self.assertEqual(2, r['max'])
self.assertEqual(4, r['sum'])
self.assertEqual(2, r['avg'])
elif grp == {'source': 'source-3'}:
self.assertEqual(1, r['count'])
self.assertEqual('s', r['unit'])
self.assertEqual(4, r['min'])
self.assertEqual(4, r['max'])
self.assertEqual(4, r['sum'])
self.assertEqual(4, r['avg'])
class TestSelectableAggregates(v2.FunctionalTest,
tests_db.MixinTestsWithBackendScenarios):
PATH = '/meters/instance/statistics'
def setUp(self):
super(TestSelectableAggregates, self).setUp()
test_sample_data = (
{'volume': 2, 'user': 'user-1', 'project': 'project-1',
'resource': 'resource-1', 'timestamp': (2013, 8, 1, 16, 10),
'metadata_flavor': 'm1.tiny', 'metadata_event': 'event-1',
'source': 'source'},
{'volume': 2, 'user': 'user-2', 'project': 'project-2',
'resource': 'resource-3', 'timestamp': (2013, 8, 1, 15, 37),
'metadata_flavor': 'm1.large', 'metadata_event': 'event-1',
'source': 'source'},
{'volume': 1, 'user': 'user-2', 'project': 'project-2',
'resource': 'resource-5', 'timestamp': (2013, 8, 1, 10, 11),
'metadata_flavor': 'm1.medium', 'metadata_event': 'event-2',
'source': 'source'},
{'volume': 2, 'user': 'user-1', 'project': 'project-1',
'resource': 'resource-2', 'timestamp': (2013, 8, 1, 10, 40),
'metadata_flavor': 'm1.large', 'metadata_event': 'event-2',
'source': 'source'},
{'volume': 2, 'user': 'user-2', 'project': 'project-2',
'resource': 'resource-4', 'timestamp': (2013, 8, 1, 14, 59),
'metadata_flavor': 'm1.large', 'metadata_event': 'event-2',
'source': 'source'},
{'volume': 5, 'user': 'user-1', 'project': 'project-1',
'resource': 'resource-2', 'timestamp': (2013, 8, 1, 17, 28),
'metadata_flavor': 'm1.large', 'metadata_event': 'event-2',
'source': 'source'},
{'volume': 4, 'user': 'user-2', 'project': 'project-2',
'resource': 'resource-3', 'timestamp': (2013, 8, 1, 11, 22),
'metadata_flavor': 'm1.large', 'metadata_event': 'event-2',
'source': 'source'},
{'volume': 9, 'user': 'user-3', 'project': 'project-3',
'resource': 'resource-4', 'timestamp': (2013, 8, 1, 11, 59),
'metadata_flavor': 'm1.large', 'metadata_event': 'event-3',
'source': 'source'},
)
for test_sample in test_sample_data:
c = sample.Sample(
'instance',
sample.TYPE_GAUGE,
unit='instance',
volume=test_sample['volume'],
user_id=test_sample['user'],
project_id=test_sample['project'],
resource_id=test_sample['resource'],
timestamp=datetime.datetime(*test_sample['timestamp']),
resource_metadata={'flavor': test_sample['metadata_flavor'],
'event': test_sample['metadata_event'], },
source=test_sample['source'],
)
msg = utils.meter_message_from_counter(
c,
self.CONF.publisher.metering_secret,
)
self.conn.record_metering_data(msg)
def _do_test_per_tenant_selectable_standard_aggregate(self,
aggregate,
expected_values):
agg_args = {'aggregate.func': aggregate}
data = self.get_json(self.PATH, groupby=['project_id'], **agg_args)
groupby_keys_set = set(x for sub_dict in data
for x in sub_dict['groupby'].keys())
groupby_vals_set = set(x for sub_dict in data
for x in sub_dict['groupby'].values())
self.assertEqual(set(['project_id']), groupby_keys_set)
projects = ['project-1', 'project-2', 'project-3']
self.assertEqual(set(projects), groupby_vals_set)
standard_aggregates = set(['count', 'min', 'max', 'sum', 'avg'])
for r in data:
grp = r['groupby']
for project in projects:
if grp == {'project_id': project}:
expected = expected_values[projects.index(project)]
self.assertEqual('instance', r['unit'])
self.assertAlmostEqual(r[aggregate], expected)
self.assertIn('aggregate', r)
self.assertIn(aggregate, r['aggregate'])
self.assertAlmostEqual(r['aggregate'][aggregate], expected)
for a in standard_aggregates - set([aggregate]):
self.assertNotIn(a, r)
def test_per_tenant_selectable_max(self):
self._do_test_per_tenant_selectable_standard_aggregate('max',
[5, 4, 9])
def test_per_tenant_selectable_min(self):
self._do_test_per_tenant_selectable_standard_aggregate('min',
[2, 1, 9])
def test_per_tenant_selectable_sum(self):
self._do_test_per_tenant_selectable_standard_aggregate('sum',
[9, 9, 9])
def test_per_tenant_selectable_avg(self):
self._do_test_per_tenant_selectable_standard_aggregate('avg',
[3, 2.25, 9])
def test_per_tenant_selectable_count(self):
self._do_test_per_tenant_selectable_standard_aggregate('count',
[3, 4, 1])
def test_per_tenant_selectable_parameterized_aggregate(self):
agg_args = {'aggregate.func': 'cardinality',
'aggregate.param': 'resource_id'}
data = self.get_json(self.PATH, groupby=['project_id'], **agg_args)
groupby_keys_set = set(x for sub_dict in data
for x in sub_dict['groupby'].keys())
groupby_vals_set = set(x for sub_dict in data
for x in sub_dict['groupby'].values())
self.assertEqual(set(['project_id']), groupby_keys_set)
projects = ['project-1', 'project-2', 'project-3']
self.assertEqual(set(projects), groupby_vals_set)
aggregate = 'cardinality/resource_id'
expected_values = [2.0, 3.0, 1.0]
standard_aggregates = set(['count', 'min', 'max', 'sum', 'avg'])
for r in data:
grp = r['groupby']
for project in projects:
if grp == {'project_id': project}:
expected = expected_values[projects.index(project)]
self.assertEqual('instance', r['unit'])
self.assertNotIn(aggregate, r)
self.assertIn('aggregate', r)
self.assertIn(aggregate, r['aggregate'])
self.assertEqual(expected, r['aggregate'][aggregate])
for a in standard_aggregates:
self.assertNotIn(a, r)
def test_large_quantum_selectable_parameterized_aggregate(self):
# add a large number of datapoints that won't impact on cardinality
# if the computation logic is tolerant of different DB behavior on
# larger numbers of samples per-period
for i in xrange(200):
s = sample.Sample(
'instance',
sample.TYPE_GAUGE,
unit='instance',
volume=i * 1.0,
user_id='user-1',
project_id='project-1',
resource_id='resource-1',
timestamp=datetime.datetime(2013, 8, 1, 11, i % 60),
resource_metadata={'flavor': 'm1.tiny',
'event': 'event-1', },
source='source',
)
msg = utils.meter_message_from_counter(
s,
self.CONF.publisher.metering_secret,
)
self.conn.record_metering_data(msg)
agg_args = {'aggregate.func': 'cardinality',
'aggregate.param': 'resource_id'}
data = self.get_json(self.PATH, **agg_args)
aggregate = 'cardinality/resource_id'
expected_value = 5.0
standard_aggregates = set(['count', 'min', 'max', 'sum', 'avg'])
r = data[0]
self.assertNotIn(aggregate, r)
self.assertIn('aggregate', r)
self.assertIn(aggregate, r['aggregate'])
self.assertEqual(expected_value, r['aggregate'][aggregate])
for a in standard_aggregates:
self.assertNotIn(a, r)
def test_repeated_unparameterized_aggregate(self):
agg_params = 'aggregate.func=count&aggregate.func=count'
data = self.get_json(self.PATH, override_params=agg_params)
aggregate = 'count'
expected_value = 8.0
standard_aggregates = set(['min', 'max', 'sum', 'avg'])
r = data[0]
self.assertIn(aggregate, r)
self.assertEqual(expected_value, r[aggregate])
self.assertIn('aggregate', r)
self.assertIn(aggregate, r['aggregate'])
self.assertEqual(expected_value, r['aggregate'][aggregate])
for a in standard_aggregates:
self.assertNotIn(a, r)
def test_fully_repeated_parameterized_aggregate(self):
agg_params = ('aggregate.func=cardinality&'
'aggregate.param=resource_id&'
'aggregate.func=cardinality&'
'aggregate.param=resource_id&')
data = self.get_json(self.PATH, override_params=agg_params)
aggregate = 'cardinality/resource_id'
expected_value = 5.0
standard_aggregates = set(['count', 'min', 'max', 'sum', 'avg'])
r = data[0]
self.assertIn('aggregate', r)
self.assertNotIn(aggregate, r)
self.assertIn(aggregate, r['aggregate'])
self.assertEqual(expected_value, r['aggregate'][aggregate])
for a in standard_aggregates:
self.assertNotIn(a, r)
def test_partially_repeated_parameterized_aggregate(self):
agg_params = ('aggregate.func=cardinality&'
'aggregate.param=resource_id&'
'aggregate.func=cardinality&'
'aggregate.param=project_id&')
data = self.get_json(self.PATH, override_params=agg_params)
expected_values = {'cardinality/resource_id': 5.0,
'cardinality/project_id': 3.0}
standard_aggregates = set(['count', 'min', 'max', 'sum', 'avg'])
r = data[0]
self.assertIn('aggregate', r)
for aggregate in expected_values.keys():
self.assertNotIn(aggregate, r)
self.assertIn(aggregate, r['aggregate'])
self.assertEqual(expected_values[aggregate],
r['aggregate'][aggregate])
for a in standard_aggregates:
self.assertNotIn(a, r)
def test_bad_selectable_parameterized_aggregate(self):
agg_args = {'aggregate.func': 'cardinality',
'aggregate.param': 'injection_attack'}
resp = self.get_json(self.PATH, status=[400],
groupby=['project_id'], **agg_args)
self.assertIn('error_message', resp)
self.assertEqual(resp['error_message'].get('faultcode'),
'Client')
self.assertEqual(resp['error_message'].get('faultstring'),
'Bad aggregate: cardinality.injection_attack')
@tests_db.run_with('mongodb', 'hbase', 'db2')
class TestUnparameterizedAggregates(v2.FunctionalTest,
tests_db.MixinTestsWithBackendScenarios):
# We put the stddev test case in a separate class so that we
# can easily exclude the sqlalchemy scenario, as sqlite doesn't
# support the stddev_pop function and fails ungracefully with
# OperationalError when it is used. However we still want to
# test the corresponding functionality in the mongo driver.
# For hbase & db2, the skip on NotImplementedError logic works
# in the usual way.
PATH = '/meters/instance/statistics'
def setUp(self):
super(TestUnparameterizedAggregates, self).setUp()
test_sample_data = (
{'volume': 2, 'user': 'user-1', 'project': 'project-1',
'resource': 'resource-1', 'timestamp': (2013, 8, 1, 16, 10),
'metadata_flavor': 'm1.tiny', 'metadata_event': 'event-1',
'source': 'source'},
{'volume': 2, 'user': 'user-2', 'project': 'project-2',
'resource': 'resource-3', 'timestamp': (2013, 8, 1, 15, 37),
'metadata_flavor': 'm1.large', 'metadata_event': 'event-1',
'source': 'source'},
{'volume': 1, 'user': 'user-2', 'project': 'project-2',
'resource': 'resource-5', 'timestamp': (2013, 8, 1, 10, 11),
'metadata_flavor': 'm1.medium', 'metadata_event': 'event-2',
'source': 'source'},
{'volume': 2, 'user': 'user-1', 'project': 'project-1',
'resource': 'resource-2', 'timestamp': (2013, 8, 1, 10, 40),
'metadata_flavor': 'm1.large', 'metadata_event': 'event-2',
'source': 'source'},
{'volume': 2, 'user': 'user-2', 'project': 'project-2',
'resource': 'resource-4', 'timestamp': (2013, 8, 1, 14, 59),
'metadata_flavor': 'm1.large', 'metadata_event': 'event-2',
'source': 'source'},
{'volume': 5, 'user': 'user-1', 'project': 'project-1',
'resource': 'resource-2', 'timestamp': (2013, 8, 1, 17, 28),
'metadata_flavor': 'm1.large', 'metadata_event': 'event-2',
'source': 'source'},
{'volume': 4, 'user': 'user-2', 'project': 'project-2',
'resource': 'resource-3', 'timestamp': (2013, 8, 1, 11, 22),
'metadata_flavor': 'm1.large', 'metadata_event': 'event-2',
'source': 'source'},
{'volume': 9, 'user': 'user-3', 'project': 'project-3',
'resource': 'resource-4', 'timestamp': (2013, 8, 1, 11, 59),
'metadata_flavor': 'm1.large', 'metadata_event': 'event-3',
'source': 'source'},
)
for test_sample in test_sample_data:
c = sample.Sample(
'instance',
sample.TYPE_GAUGE,
unit='instance',
volume=test_sample['volume'],
user_id=test_sample['user'],
project_id=test_sample['project'],
resource_id=test_sample['resource'],
timestamp=datetime.datetime(*test_sample['timestamp']),
resource_metadata={'flavor': test_sample['metadata_flavor'],
'event': test_sample['metadata_event'], },
source=test_sample['source'],
)
msg = utils.meter_message_from_counter(
c,
self.CONF.publisher.metering_secret,
)
self.conn.record_metering_data(msg)
def test_per_tenant_selectable_unparameterized_aggregate(self):
agg_args = {'aggregate.func': 'stddev'}
data = self.get_json(self.PATH, groupby=['project_id'], **agg_args)
groupby_keys_set = set(x for sub_dict in data
for x in sub_dict['groupby'].keys())
groupby_vals_set = set(x for sub_dict in data
for x in sub_dict['groupby'].values())
self.assertEqual(set(['project_id']), groupby_keys_set)
projects = ['project-1', 'project-2', 'project-3']
self.assertEqual(set(projects), groupby_vals_set)
aggregate = 'stddev'
expected_values = [1.4142, 1.0897, 0.0]
standard_aggregates = set(['count', 'min', 'max', 'sum', 'avg'])
for r in data:
grp = r['groupby']
for project in projects:
if grp == {'project_id': project}:
expected = expected_values[projects.index(project)]
self.assertEqual('instance', r['unit'])
self.assertNotIn(aggregate, r)
self.assertIn('aggregate', r)
self.assertIn(aggregate, r['aggregate'])
self.assertAlmostEqual(r['aggregate'][aggregate],
expected,
places=4)
for a in standard_aggregates:
self.assertNotIn(a, r)