Fix Influx statistics and Alarm History behavior

Fix influx statistics query to include the timestamp offset

Fix monasca_tempest_tests.tests.api.test_statistics.TestStatistics.test_list_statistics_with_offset_limit by
assuming offset is an opaque value and making sure it is urldecoded and urlencoded as it should be. Also,
previously, the test was trying to use an offset returned by measurement-list and apply it to metric-statistics.
That is not required to work by the API definition and should not be attempted

There was a bug in the Java parsing of timestamps which was causing
2016-08-05T17:33:13.310Z to be converted to 2016-08-05T17:33:13.031Z. This caused
Alarm Histories to be appear to be out of order which caused the tests to fail randomly.
Fixed that bug and added unit tests

Change-Id: Iedccae6584e01c56cc05dcc45f9b124cb7d61109
This commit is contained in:
Ryan Brandt 2016-08-15 16:28:04 -06:00 committed by Craig Bryant
parent 74e2f8109e
commit b6a6a325e7
3 changed files with 56 additions and 41 deletions

View File

@ -1,4 +1,4 @@
# (C) Copyright 2015-2016 Hewlett Packard Enterprise Development Company LP
# (C) Copyright 2015-2016 Hewlett Packard Enterprise Development LP
#
# 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
@ -11,6 +11,8 @@
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import six.moves.urllib.parse as urlparse
from tempest import config
from tempest.common import credentials_factory
import tempest.test
@ -76,3 +78,20 @@ class BaseMonascaTest(tempest.test.BaseTestCase):
id = element['id']
cls.monasca_client.delete_alarm(id)
cls.cred_provider.clear_creds()
def _get_offset(self, response_body):
next_link = None
self_link = None
for link in response_body['links']:
if link['rel'] == 'next':
next_link = link['href']
if link['rel'] == 'self':
self_link = link['href']
if not next_link:
query_parms = urlparse.parse_qs(urlparse.urlparse(self_link).query)
self.fail("No next link returned with query parameters: {}".format(query_parms))
query_params = urlparse.parse_qs(urlparse.urlparse(next_link).query)
if 'offset' not in query_params:
self.fail("No offset in next link: {}".format(next_link))
return query_params['offset'][0]

View File

@ -47,11 +47,8 @@ class TestAlarmsStateHistoryOneTransition(base.BaseMonascaTest):
# MIN_HISTORY number of Alarms State History are needed.
metric = helpers.create_metric(name="name-" + str(i + 1))
cls.monasca_client.create_metrics(metric)
# sleep 1 second between metrics to make sure timestamps
# are different in the second field. Influxdb has a bug
# where it does not sort properly by milliseconds. .014
# is sorted as greater than .138
time.sleep(1.0)
# Ensure alarms transition at different times
time.sleep(0.1)
resp, response_body = cls.monasca_client.\
list_alarms_state_history()
elements = response_body['elements']

View File

@ -1,4 +1,4 @@
# (C) Copyright 2015-2016 Hewlett Packard Enterprise Development Company LP
# (C) Copyright 2015-2016 Hewlett Packard Enterprise Development LP
#
# 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
@ -22,6 +22,7 @@ from monasca_tempest_tests.tests.api import helpers
from tempest.common.utils import data_utils
from tempest import test
from tempest.lib import exceptions
from urllib import urlencode
NUM_MEASUREMENTS = 100
MIN_REQUIRED_MEASUREMENTS = 2
@ -198,6 +199,7 @@ class TestStatistics(base.BaseMonascaTest):
value=4)
]
num_metrics = len(metric)
self.monasca_client.create_metrics(metric)
query_parms = '?name=' + name
for i in xrange(constants.MAX_RETRIES):
@ -208,7 +210,7 @@ class TestStatistics(base.BaseMonascaTest):
break
else:
time.sleep(constants.RETRY_WAIT_SECS)
self._check_timeout(i, constants.MAX_RETRIES, elements, 4)
self._check_timeout(i, constants.MAX_RETRIES, elements, num_metrics)
start_time = helpers.timestamp_to_iso(start_timestamp)
end_timestamp = start_timestamp + 4000
@ -223,42 +225,35 @@ class TestStatistics(base.BaseMonascaTest):
query_parms = '?name=' + name + '&merge_metrics=true&statistics=avg'\
+ '&start_time=' + str(start_time) + '&end_time=' + \
str(end_time) + '&period=1' + '&limit=4'
str(end_time) + '&period=1' + '&limit=' + str(num_metrics)
resp, response_body = self.monasca_client.list_statistics(
query_parms)
self.assertEqual(200, resp.status)
elements = response_body['elements'][0]['statistics']
self.assertEqual(4, len(elements))
self.assertEqual(num_metrics, len(elements))
self.assertEqual(first_element, elements[0])
for index in xrange(1, 4):
max_limit = 4 - index
for limit in xrange(1, num_metrics):
start_index = 0
params = [('name', name),
('merge_metrics', 'true'),
('statistics', 'avg'),
('start_time', str(start_time)),
('end_time', str(end_time)),
('period', 1),
('limit', limit)
]
offset = None
while True:
num_expected_elements = limit
if (num_expected_elements + start_index) > num_metrics:
num_expected_elements = num_metrics - start_index
# Get first offset from api
query_parms = '?name=' + str(name) + \
'&merge_metrics=true&start_time=' + elements[index - 1][0] + \
'&end_time=' + end_time + \
'&limit=1'
resp, response_body = self.monasca_client.list_measurements(query_parms)
for link in response_body['links']:
if link['rel'] == 'next':
next_link = link['href']
if not next_link:
self.fail("No next link returned with query parameters: {}".formet(query_parms))
offset = helpers.get_query_param(next_link, "offset")
# python api returns exact timestamp, but the test needs a rounded number
offset_period_index = offset.find('.')
offset = offset[:offset_period_index] + 'Z'
for limit in xrange(1, max_limit):
expected_elements = [elem for elem in elements if elem[0] > offset]
expected_elements = expected_elements[:limit]
query_parms = '?name=' + name + '&merge_metrics=true' + \
'&statistics=avg' + '&start_time=' + \
str(start_time) + '&end_time=' + \
str(end_time) + '&period=1' + '&limit=' + \
str(limit) + '&offset=' + str(offset)
these_params = list(params)
# If not the first call, use the offset returned by the last call
if offset:
these_params.extend([('offset', str(offset))])
query_parms = '?' + urlencode(these_params)
resp, response_body = self.monasca_client.list_statistics(query_parms)
self.assertEqual(200, resp.status)
if not response_body['elements']:
@ -267,10 +262,14 @@ class TestStatistics(base.BaseMonascaTest):
self.fail("No statistics returned")
new_elements = response_body['elements'][0]['statistics']
self.assertEqual(limit, len(new_elements))
# bug in the python API causes limit 1 to not have matching timestamps
if limit > 1:
self.assertEqual(expected_elements, new_elements)
self.assertEqual(num_expected_elements, len(new_elements))
expected_elements = elements[start_index:start_index+limit]
self.assertEqual(expected_elements, new_elements)
start_index += num_expected_elements
if start_index >= num_metrics:
break
# Get the next set
offset = self._get_offset(response_body)
@test.attr(type="gate")