Merge "Remove Ceilometer tempest tests"
This commit is contained in:
commit
c2c90574a7
@ -61,5 +61,3 @@ objects:
|
||||
owner: javelin
|
||||
file: /etc/hosts
|
||||
swift_role: Member
|
||||
|
||||
telemetry: true
|
@ -1,196 +0,0 @@
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import time
|
||||
|
||||
from oslo_utils import timeutils
|
||||
|
||||
from tempest.common import compute
|
||||
from tempest.common.utils import data_utils
|
||||
from tempest.common import waiters
|
||||
from tempest import config
|
||||
from tempest import exceptions
|
||||
from tempest.lib import exceptions as lib_exc
|
||||
import tempest.test
|
||||
|
||||
CONF = config.CONF
|
||||
|
||||
|
||||
class BaseTelemetryTest(tempest.test.BaseTestCase):
|
||||
|
||||
"""Base test case class for all Telemetry API tests."""
|
||||
|
||||
credentials = ['primary']
|
||||
|
||||
@classmethod
|
||||
def skip_checks(cls):
|
||||
super(BaseTelemetryTest, cls).skip_checks()
|
||||
if not CONF.service_available.ceilometer:
|
||||
raise cls.skipException("Ceilometer support is required")
|
||||
|
||||
@classmethod
|
||||
def setup_credentials(cls):
|
||||
cls.set_network_resources()
|
||||
super(BaseTelemetryTest, cls).setup_credentials()
|
||||
|
||||
@classmethod
|
||||
def setup_clients(cls):
|
||||
super(BaseTelemetryTest, cls).setup_clients()
|
||||
cls.telemetry_client = cls.os.telemetry_client
|
||||
cls.servers_client = cls.os.servers_client
|
||||
cls.flavors_client = cls.os.flavors_client
|
||||
cls.image_client = cls.os.image_client
|
||||
cls.image_client_v2 = cls.os.image_client_v2
|
||||
|
||||
@classmethod
|
||||
def resource_setup(cls):
|
||||
super(BaseTelemetryTest, cls).resource_setup()
|
||||
cls.nova_notifications = ['memory', 'vcpus', 'disk.root.size',
|
||||
'disk.ephemeral.size']
|
||||
|
||||
cls.glance_notifications = ['image.size']
|
||||
|
||||
cls.glance_v2_notifications = ['image.download', 'image.serve']
|
||||
|
||||
cls.server_ids = []
|
||||
cls.image_ids = []
|
||||
|
||||
@classmethod
|
||||
def create_server(cls):
|
||||
tenant_network = cls.get_tenant_network()
|
||||
body, server = compute.create_test_server(
|
||||
cls.os,
|
||||
tenant_network=tenant_network,
|
||||
name=data_utils.rand_name('ceilometer-instance'),
|
||||
wait_until='ACTIVE')
|
||||
cls.server_ids.append(body['id'])
|
||||
return body
|
||||
|
||||
@classmethod
|
||||
def create_image(cls, client, **kwargs):
|
||||
body = client.create_image(name=data_utils.rand_name('image'),
|
||||
container_format='bare',
|
||||
disk_format='raw',
|
||||
**kwargs)
|
||||
# TODO(jswarren) Move ['image'] up to initial body value assignment
|
||||
# once both v1 and v2 glance clients include the full response
|
||||
# object.
|
||||
if 'image' in body:
|
||||
body = body['image']
|
||||
cls.image_ids.append(body['id'])
|
||||
return body
|
||||
|
||||
@staticmethod
|
||||
def cleanup_resources(method, list_of_ids):
|
||||
for resource_id in list_of_ids:
|
||||
try:
|
||||
method(resource_id)
|
||||
except lib_exc.NotFound:
|
||||
pass
|
||||
|
||||
@classmethod
|
||||
def wait_for_server_termination(cls, server_id):
|
||||
waiters.wait_for_server_termination(cls.servers_client,
|
||||
server_id)
|
||||
|
||||
@classmethod
|
||||
def resource_cleanup(cls):
|
||||
cls.cleanup_resources(cls.servers_client.delete_server, cls.server_ids)
|
||||
cls.cleanup_resources(cls.wait_for_server_termination, cls.server_ids)
|
||||
cls.cleanup_resources(cls.image_client.delete_image, cls.image_ids)
|
||||
super(BaseTelemetryTest, cls).resource_cleanup()
|
||||
|
||||
def await_samples(self, metric, query):
|
||||
"""This method is to wait for sample to add it to database.
|
||||
|
||||
There are long time delays when using Postgresql (or Mysql)
|
||||
database as ceilometer backend
|
||||
"""
|
||||
timeout = CONF.compute.build_timeout
|
||||
start = timeutils.utcnow()
|
||||
while timeutils.delta_seconds(start, timeutils.utcnow()) < timeout:
|
||||
body = self.telemetry_client.list_samples(metric, query)
|
||||
if body:
|
||||
return body
|
||||
time.sleep(CONF.compute.build_interval)
|
||||
|
||||
raise exceptions.TimeoutException(
|
||||
'Sample for metric:%s with query:%s has not been added to the '
|
||||
'database within %d seconds' % (metric, query,
|
||||
CONF.compute.build_timeout))
|
||||
|
||||
|
||||
class BaseTelemetryAdminTest(BaseTelemetryTest):
|
||||
"""Base test case class for admin Telemetry API tests."""
|
||||
|
||||
credentials = ['primary', 'admin']
|
||||
|
||||
@classmethod
|
||||
def setup_clients(cls):
|
||||
super(BaseTelemetryAdminTest, cls).setup_clients()
|
||||
cls.telemetry_admin_client = cls.os_adm.telemetry_client
|
||||
|
||||
def await_events(self, query):
|
||||
timeout = CONF.compute.build_timeout
|
||||
start = timeutils.utcnow()
|
||||
while timeutils.delta_seconds(start, timeutils.utcnow()) < timeout:
|
||||
body = self.telemetry_admin_client.list_events(query)
|
||||
if body:
|
||||
return body
|
||||
time.sleep(CONF.compute.build_interval)
|
||||
|
||||
raise exceptions.TimeoutException(
|
||||
'Event with query:%s has not been added to the '
|
||||
'database within %d seconds' % (query, CONF.compute.build_timeout))
|
||||
|
||||
|
||||
class BaseAlarmingTest(tempest.test.BaseTestCase):
|
||||
"""Base test case class for all Alarming API tests."""
|
||||
|
||||
credentials = ['primary']
|
||||
|
||||
@classmethod
|
||||
def skip_checks(cls):
|
||||
super(BaseAlarmingTest, cls).skip_checks()
|
||||
if not CONF.service_available.aodh:
|
||||
raise cls.skipException("Aodh support is required")
|
||||
|
||||
@classmethod
|
||||
def setup_clients(cls):
|
||||
super(BaseAlarmingTest, cls).setup_clients()
|
||||
cls.alarming_client = cls.os.alarming_client
|
||||
|
||||
@classmethod
|
||||
def resource_setup(cls):
|
||||
super(BaseAlarmingTest, cls).resource_setup()
|
||||
cls.alarm_ids = []
|
||||
|
||||
@classmethod
|
||||
def create_alarm(cls, **kwargs):
|
||||
body = cls.alarming_client.create_alarm(
|
||||
name=data_utils.rand_name('telemetry_alarm'),
|
||||
type='threshold', **kwargs)
|
||||
cls.alarm_ids.append(body['alarm_id'])
|
||||
return body
|
||||
|
||||
@staticmethod
|
||||
def cleanup_resources(method, list_of_ids):
|
||||
for resource_id in list_of_ids:
|
||||
try:
|
||||
method(resource_id)
|
||||
except lib_exc.NotFound:
|
||||
pass
|
||||
|
||||
@classmethod
|
||||
def resource_cleanup(cls):
|
||||
cls.cleanup_resources(cls.alarming_client.delete_alarm, cls.alarm_ids)
|
||||
super(BaseAlarmingTest, cls).resource_cleanup()
|
@ -1,110 +0,0 @@
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from tempest.api.telemetry import base
|
||||
from tempest.common.utils import data_utils
|
||||
from tempest.lib import exceptions as lib_exc
|
||||
from tempest import test
|
||||
|
||||
|
||||
class TelemetryAlarmingAPITestJSON(base.BaseAlarmingTest):
|
||||
|
||||
@classmethod
|
||||
def resource_setup(cls):
|
||||
super(TelemetryAlarmingAPITestJSON, cls).resource_setup()
|
||||
cls.rule = {'meter_name': 'cpu_util',
|
||||
'comparison_operator': 'gt',
|
||||
'threshold': 80.0,
|
||||
'period': 70}
|
||||
for i in range(2):
|
||||
cls.create_alarm(threshold_rule=cls.rule)
|
||||
|
||||
@test.idempotent_id('1c918e06-210b-41eb-bd45-14676dd77cd6')
|
||||
def test_alarm_list(self):
|
||||
# List alarms
|
||||
alarm_list = self.alarming_client.list_alarms()
|
||||
|
||||
# Verify created alarm in the list
|
||||
fetched_ids = [a['alarm_id'] for a in alarm_list]
|
||||
missing_alarms = [a for a in self.alarm_ids if a not in fetched_ids]
|
||||
self.assertEqual(0, len(missing_alarms),
|
||||
"Failed to find the following created alarm(s)"
|
||||
" in a fetched list: %s" %
|
||||
', '.join(str(a) for a in missing_alarms))
|
||||
|
||||
@test.idempotent_id('1297b095-39c1-4e74-8a1f-4ae998cedd67')
|
||||
def test_create_update_get_delete_alarm(self):
|
||||
# Create an alarm
|
||||
alarm_name = data_utils.rand_name('telemetry_alarm')
|
||||
body = self.alarming_client.create_alarm(
|
||||
name=alarm_name, type='threshold', threshold_rule=self.rule)
|
||||
self.assertEqual(alarm_name, body['name'])
|
||||
alarm_id = body['alarm_id']
|
||||
self.assertDictContainsSubset(self.rule, body['threshold_rule'])
|
||||
# Update alarm with new rule and new name
|
||||
new_rule = {'meter_name': 'cpu',
|
||||
'comparison_operator': 'eq',
|
||||
'threshold': 70.0,
|
||||
'period': 60}
|
||||
alarm_name_updated = data_utils.rand_name('telemetry-alarm-update')
|
||||
body = self.alarming_client.update_alarm(
|
||||
alarm_id,
|
||||
threshold_rule=new_rule,
|
||||
name=alarm_name_updated,
|
||||
type='threshold')
|
||||
self.assertEqual(alarm_name_updated, body['name'])
|
||||
self.assertDictContainsSubset(new_rule, body['threshold_rule'])
|
||||
# Get and verify details of an alarm after update
|
||||
body = self.alarming_client.show_alarm(alarm_id)
|
||||
self.assertEqual(alarm_name_updated, body['name'])
|
||||
self.assertDictContainsSubset(new_rule, body['threshold_rule'])
|
||||
# Get history for the alarm and verify the same
|
||||
body = self.alarming_client.show_alarm_history(alarm_id)
|
||||
self.assertEqual("rule change", body[0]['type'])
|
||||
self.assertIn(alarm_name_updated, body[0]['detail'])
|
||||
self.assertEqual("creation", body[1]['type'])
|
||||
self.assertIn(alarm_name, body[1]['detail'])
|
||||
# Delete alarm and verify if deleted
|
||||
self.alarming_client.delete_alarm(alarm_id)
|
||||
self.assertRaises(lib_exc.NotFound,
|
||||
self.alarming_client.show_alarm, alarm_id)
|
||||
|
||||
@test.idempotent_id('aca49486-70bb-4016-87e0-f6131374f741')
|
||||
def test_set_get_alarm_state(self):
|
||||
alarm_states = ['ok', 'alarm', 'insufficient data']
|
||||
alarm = self.create_alarm(threshold_rule=self.rule)
|
||||
# Set alarm state and verify
|
||||
new_state =\
|
||||
[elem for elem in alarm_states if elem != alarm['state']][0]
|
||||
state = self.alarming_client.alarm_set_state(alarm['alarm_id'],
|
||||
new_state)
|
||||
self.assertEqual(new_state, state.data)
|
||||
# Get alarm state and verify
|
||||
state = self.alarming_client.show_alarm_state(alarm['alarm_id'])
|
||||
self.assertEqual(new_state, state.data)
|
||||
|
||||
@test.idempotent_id('08d7e45a-1344-4e5c-ba6f-f6cbb77f55b9')
|
||||
def test_create_delete_alarm_with_combination_rule(self):
|
||||
rule = {"alarm_ids": self.alarm_ids,
|
||||
"operator": "or"}
|
||||
# Verifies alarm create
|
||||
alarm_name = data_utils.rand_name('combination_alarm')
|
||||
body = self.alarming_client.create_alarm(name=alarm_name,
|
||||
combination_rule=rule,
|
||||
type='combination')
|
||||
self.assertEqual(alarm_name, body['name'])
|
||||
alarm_id = body['alarm_id']
|
||||
self.assertDictContainsSubset(rule, body['combination_rule'])
|
||||
# Verify alarm delete
|
||||
self.alarming_client.delete_alarm(alarm_id)
|
||||
self.assertRaises(lib_exc.NotFound,
|
||||
self.alarming_client.show_alarm, alarm_id)
|
@ -1,69 +0,0 @@
|
||||
# Copyright 2015 GlobalLogic. All rights reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from tempest.api.telemetry import base
|
||||
from tempest.common.utils import data_utils
|
||||
from tempest.lib import exceptions as lib_exc
|
||||
from tempest import test
|
||||
|
||||
|
||||
class TelemetryAlarmingNegativeTest(base.BaseAlarmingTest):
|
||||
"""Negative tests for show_alarm, update_alarm, show_alarm_history tests
|
||||
|
||||
** show non-existent alarm
|
||||
** show the deleted alarm
|
||||
** delete deleted alarm
|
||||
** update deleted alarm
|
||||
"""
|
||||
|
||||
@test.attr(type=['negative'])
|
||||
@test.idempotent_id('668743d5-08ad-4480-b2b8-15da34f81e7d')
|
||||
def test_get_non_existent_alarm(self):
|
||||
# get the non-existent alarm
|
||||
non_existent_id = data_utils.rand_uuid()
|
||||
self.assertRaises(lib_exc.NotFound, self.alarming_client.show_alarm,
|
||||
non_existent_id)
|
||||
|
||||
@test.attr(type=['negative'])
|
||||
@test.idempotent_id('ef45000d-0a72-4781-866d-4cb7bf2582ad')
|
||||
def test_get_update_show_history_delete_deleted_alarm(self):
|
||||
# get, update and delete the deleted alarm
|
||||
alarm_name = data_utils.rand_name('telemetry_alarm')
|
||||
rule = {'meter_name': 'cpu',
|
||||
'comparison_operator': 'eq',
|
||||
'threshold': 100.0,
|
||||
'period': 90}
|
||||
body = self.alarming_client.create_alarm(
|
||||
name=alarm_name,
|
||||
type='threshold',
|
||||
threshold_rule=rule)
|
||||
alarm_id = body['alarm_id']
|
||||
self.alarming_client.delete_alarm(alarm_id)
|
||||
# get the deleted alarm
|
||||
self.assertRaises(lib_exc.NotFound, self.alarming_client.show_alarm,
|
||||
alarm_id)
|
||||
|
||||
# update the deleted alarm
|
||||
updated_alarm_name = data_utils.rand_name('telemetry_alarm_updated')
|
||||
updated_rule = {'meter_name': 'cpu_new',
|
||||
'comparison_operator': 'eq',
|
||||
'threshold': 70,
|
||||
'period': 50}
|
||||
self.assertRaises(lib_exc.NotFound, self.alarming_client.update_alarm,
|
||||
alarm_id, threshold_rule=updated_rule,
|
||||
name=updated_alarm_name,
|
||||
type='threshold')
|
||||
# delete the deleted alarm
|
||||
self.assertRaises(lib_exc.NotFound, self.alarming_client.delete_alarm,
|
||||
alarm_id)
|
@ -1,84 +0,0 @@
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import testtools
|
||||
|
||||
from tempest.api.telemetry import base
|
||||
from tempest import config
|
||||
from tempest.lib import decorators
|
||||
from tempest import test
|
||||
|
||||
CONF = config.CONF
|
||||
|
||||
|
||||
class TelemetryNotificationAPITestJSON(base.BaseTelemetryTest):
|
||||
|
||||
@test.idempotent_id('d7f8c1c8-d470-4731-8604-315d3956caad')
|
||||
@test.services('compute')
|
||||
def test_check_nova_notification(self):
|
||||
|
||||
body = self.create_server()
|
||||
|
||||
query = ('resource', 'eq', body['id'])
|
||||
|
||||
for metric in self.nova_notifications:
|
||||
self.await_samples(metric, query)
|
||||
|
||||
@test.attr(type="smoke")
|
||||
@test.idempotent_id('04b10bfe-a5dc-47af-b22f-0460426bf498')
|
||||
@test.services("image")
|
||||
@testtools.skipIf(not CONF.image_feature_enabled.api_v1,
|
||||
"Glance api v1 is disabled")
|
||||
def test_check_glance_v1_notifications(self):
|
||||
body = self.create_image(self.image_client, is_public=False)
|
||||
self.image_client.update_image(body['id'], data='data')
|
||||
|
||||
query = 'resource', 'eq', body['id']
|
||||
|
||||
self.image_client.delete_image(body['id'])
|
||||
|
||||
for metric in self.glance_notifications:
|
||||
self.await_samples(metric, query)
|
||||
|
||||
@test.attr(type="smoke")
|
||||
@test.idempotent_id('c240457d-d943-439b-8aea-85e26d64fe8e')
|
||||
@test.services("image")
|
||||
@testtools.skipIf(not CONF.image_feature_enabled.api_v2,
|
||||
"Glance api v2 is disabled")
|
||||
def test_check_glance_v2_notifications(self):
|
||||
body = self.create_image(self.image_client_v2, visibility='private')
|
||||
|
||||
self.image_client_v2.store_image_file(body['id'], "file")
|
||||
self.image_client_v2.show_image_file(body['id'])
|
||||
|
||||
query = 'resource', 'eq', body['id']
|
||||
|
||||
for metric in self.glance_v2_notifications:
|
||||
self.await_samples(metric, query)
|
||||
|
||||
|
||||
class TelemetryNotificationAdminAPITestJSON(base.BaseTelemetryAdminTest):
|
||||
|
||||
@test.idempotent_id('29604198-8b45-4fc0-8af8-1cae4f94ebe9')
|
||||
@test.services('compute')
|
||||
@decorators.skip_because(bug='1480490')
|
||||
def test_check_nova_notification_event_and_meter(self):
|
||||
|
||||
body = self.create_server()
|
||||
|
||||
if CONF.telemetry_feature_enabled.events:
|
||||
query = ('instance_id', 'eq', body['id'])
|
||||
self.await_events(query)
|
||||
|
||||
query = ('resource', 'eq', body['id'])
|
||||
for metric in self.nova_notifications:
|
||||
self.await_samples(metric, query)
|
@ -138,9 +138,6 @@ from tempest.services.object_storage.container_client import ContainerClient
|
||||
from tempest.services.object_storage.object_client import ObjectClient
|
||||
from tempest.services.orchestration.json.orchestration_client import \
|
||||
OrchestrationClient
|
||||
from tempest.services.telemetry.json.alarming_client import AlarmingClient
|
||||
from tempest.services.telemetry.json.telemetry_client import \
|
||||
TelemetryClient
|
||||
from tempest.services.volume.v1.json.admin.hosts_client import \
|
||||
HostsClient as VolumeHostsClient
|
||||
from tempest.services.volume.v1.json.admin.quotas_client import \
|
||||
@ -324,20 +321,6 @@ class Manager(manager.Manager):
|
||||
build_interval=CONF.network.build_interval,
|
||||
build_timeout=CONF.network.build_timeout,
|
||||
**self.default_params)
|
||||
if CONF.service_available.ceilometer:
|
||||
self.telemetry_client = TelemetryClient(
|
||||
self.auth_provider,
|
||||
CONF.telemetry.catalog_type,
|
||||
CONF.identity.region,
|
||||
endpoint_type=CONF.telemetry.endpoint_type,
|
||||
**self.default_params_with_timeout_values)
|
||||
if CONF.service_available.aodh:
|
||||
self.alarming_client = AlarmingClient(
|
||||
self.auth_provider,
|
||||
CONF.alarming.catalog_type,
|
||||
CONF.identity.region,
|
||||
endpoint_type=CONF.alarming.endpoint_type,
|
||||
**self.default_params_with_timeout_values)
|
||||
if CONF.service_available.glance:
|
||||
self.image_client = ImagesClient(
|
||||
self.auth_provider,
|
||||
|
@ -33,7 +33,6 @@ CONF_PUB_ROUTER = None
|
||||
CONF_TENANTS = None
|
||||
CONF_USERS = None
|
||||
|
||||
IS_AODH = None
|
||||
IS_CINDER = None
|
||||
IS_GLANCE = None
|
||||
IS_HEAT = None
|
||||
@ -51,14 +50,12 @@ def init_conf():
|
||||
global CONF_PUB_ROUTER
|
||||
global CONF_TENANTS
|
||||
global CONF_USERS
|
||||
global IS_AODH
|
||||
global IS_CINDER
|
||||
global IS_GLANCE
|
||||
global IS_HEAT
|
||||
global IS_NEUTRON
|
||||
global IS_NOVA
|
||||
|
||||
IS_AODH = CONF.service_available.aodh
|
||||
IS_CINDER = CONF.service_available.cinder
|
||||
IS_GLANCE = CONF.service_available.glance
|
||||
IS_HEAT = CONF.service_available.heat
|
||||
@ -706,32 +703,6 @@ class NetworkSubnetService(NetworkService):
|
||||
self.data['subnets'] = subnets
|
||||
|
||||
|
||||
# Telemetry services
|
||||
class TelemetryAlarmService(BaseService):
|
||||
def __init__(self, manager, **kwargs):
|
||||
super(TelemetryAlarmService, self).__init__(kwargs)
|
||||
self.client = manager.alarming_client
|
||||
|
||||
def list(self):
|
||||
client = self.client
|
||||
alarms = client.list_alarms()
|
||||
LOG.debug("List count, %s Alarms" % len(alarms))
|
||||
return alarms
|
||||
|
||||
def delete(self):
|
||||
client = self.client
|
||||
alarms = self.list()
|
||||
for alarm in alarms:
|
||||
try:
|
||||
client.delete_alarm(alarm['id'])
|
||||
except Exception:
|
||||
LOG.exception("Delete Alarms exception.")
|
||||
|
||||
def dry_run(self):
|
||||
alarms = self.list()
|
||||
self.data['alarms'] = alarms
|
||||
|
||||
|
||||
# begin global services
|
||||
class FlavorService(BaseService):
|
||||
def __init__(self, manager, **kwargs):
|
||||
@ -976,8 +947,8 @@ class DomainService(BaseService):
|
||||
|
||||
def get_tenant_cleanup_services():
|
||||
tenant_services = []
|
||||
if IS_AODH:
|
||||
tenant_services.append(TelemetryAlarmService)
|
||||
# TODO(gmann): Tempest should provide some plugin hook for cleanup
|
||||
# script extension to plugin tests also.
|
||||
if IS_NOVA:
|
||||
tenant_services.append(ServerService)
|
||||
tenant_services.append(KeyPairService)
|
||||
|
@ -113,7 +113,6 @@ import unittest
|
||||
|
||||
import netaddr
|
||||
from oslo_log import log as logging
|
||||
from oslo_utils import timeutils
|
||||
import six
|
||||
import yaml
|
||||
|
||||
@ -138,8 +137,6 @@ from tempest.services.image.v2.json import images_client
|
||||
from tempest.services.network.json import routers_client
|
||||
from tempest.services.object_storage import container_client
|
||||
from tempest.services.object_storage import object_client
|
||||
from tempest.services.telemetry.json import alarming_client
|
||||
from tempest.services.telemetry.json import telemetry_client
|
||||
from tempest.services.volume.v1.json import volumes_client
|
||||
|
||||
CONF = config.CONF
|
||||
@ -244,18 +241,6 @@ class OSClient(object):
|
||||
build_interval=CONF.image.build_interval,
|
||||
build_timeout=CONF.image.build_timeout,
|
||||
**default_params)
|
||||
self.telemetry = telemetry_client.TelemetryClient(
|
||||
_auth,
|
||||
CONF.telemetry.catalog_type,
|
||||
CONF.identity.region,
|
||||
endpoint_type=CONF.telemetry.endpoint_type,
|
||||
**default_params_with_timeout_values)
|
||||
self.alarming = alarming_client.AlarmingClient(
|
||||
_auth,
|
||||
CONF.alarm.catalog_type,
|
||||
CONF.identity.region,
|
||||
endpoint_type=CONF.alarm.endpoint_type,
|
||||
**default_params_with_timeout_values)
|
||||
self.volumes = volumes_client.VolumesClient(
|
||||
_auth,
|
||||
CONF.volume.catalog_type,
|
||||
@ -461,7 +446,6 @@ class JavelinCheck(unittest.TestCase):
|
||||
self.check_objects()
|
||||
self.check_servers()
|
||||
self.check_volumes()
|
||||
self.check_telemetry()
|
||||
self.check_secgroups()
|
||||
|
||||
# validate neutron is enabled and ironic disabled:
|
||||
@ -563,27 +547,6 @@ class JavelinCheck(unittest.TestCase):
|
||||
found,
|
||||
"Couldn't find expected secgroup %s" % secgroup['name'])
|
||||
|
||||
def check_telemetry(self):
|
||||
"""Check that ceilometer provides a sane sample.
|
||||
|
||||
Confirm that there is more than one sample and that they have the
|
||||
expected metadata.
|
||||
|
||||
If in check mode confirm that the oldest sample available is from
|
||||
before the upgrade.
|
||||
"""
|
||||
if not self.res.get('telemetry'):
|
||||
return
|
||||
LOG.info("checking telemetry")
|
||||
for server in self.res['servers']:
|
||||
client = client_for_user(server['owner'])
|
||||
body = client.telemetry.list_samples(
|
||||
'instance',
|
||||
query=('metadata.display_name', 'eq', server['name'])
|
||||
)
|
||||
self.assertTrue(len(body) >= 1, 'expecting at least one sample')
|
||||
self._confirm_telemetry_sample(server, body[-1])
|
||||
|
||||
def check_volumes(self):
|
||||
"""Check that the volumes are still there and attached."""
|
||||
if not self.res.get('volumes'):
|
||||
@ -602,26 +565,6 @@ class JavelinCheck(unittest.TestCase):
|
||||
self.assertEqual(vol_body['id'], attachment['volume_id'])
|
||||
self.assertEqual(server_id, attachment['server_id'])
|
||||
|
||||
def _confirm_telemetry_sample(self, server, sample):
|
||||
"""Check this sample matches the expected resource metadata."""
|
||||
# Confirm display_name
|
||||
self.assertEqual(server['name'],
|
||||
sample['resource_metadata']['display_name'])
|
||||
# Confirm instance_type of flavor
|
||||
flavor = sample['resource_metadata'].get(
|
||||
'flavor.name',
|
||||
sample['resource_metadata'].get('instance_type')
|
||||
)
|
||||
self.assertEqual(server['flavor'], flavor)
|
||||
# Confirm the oldest sample was created before upgrade.
|
||||
if OPTS.mode == 'check':
|
||||
oldest_timestamp = timeutils.normalize_time(
|
||||
timeutils.parse_isotime(sample['timestamp']))
|
||||
self.assertTrue(
|
||||
oldest_timestamp < JAVELIN_START,
|
||||
'timestamp should come before start of second javelin run'
|
||||
)
|
||||
|
||||
def check_networking(self):
|
||||
"""Check that the networks are still there."""
|
||||
for res_type in ('networks', 'subnets', 'routers'):
|
||||
|
@ -93,4 +93,3 @@ objects:
|
||||
name: javelin1
|
||||
owner: javelin
|
||||
file: /etc/hosts
|
||||
telemetry: true
|
||||
|
@ -282,8 +282,6 @@ def check_service_availability(os, update):
|
||||
'object_storage': 'swift',
|
||||
'compute': 'nova',
|
||||
'orchestration': 'heat',
|
||||
'metering': 'ceilometer',
|
||||
'telemetry': 'ceilometer',
|
||||
'data_processing': 'sahara',
|
||||
'baremetal': 'ironic',
|
||||
'identity': 'keystone',
|
||||
|
@ -882,50 +882,6 @@ OrchestrationGroup = [
|
||||
]
|
||||
|
||||
|
||||
telemetry_group = cfg.OptGroup(name='telemetry',
|
||||
title='Telemetry Service Options')
|
||||
|
||||
TelemetryGroup = [
|
||||
cfg.StrOpt('catalog_type',
|
||||
default='metering',
|
||||
help="Catalog type of the Telemetry service."),
|
||||
cfg.StrOpt('endpoint_type',
|
||||
default='publicURL',
|
||||
choices=['public', 'admin', 'internal',
|
||||
'publicURL', 'adminURL', 'internalURL'],
|
||||
help="The endpoint type to use for the telemetry service."),
|
||||
cfg.BoolOpt('too_slow_to_test',
|
||||
default=True,
|
||||
deprecated_for_removal=True,
|
||||
help="This variable is used as flag to enable "
|
||||
"notification tests")
|
||||
]
|
||||
|
||||
alarming_group = cfg.OptGroup(name='alarming',
|
||||
title='Alarming Service Options')
|
||||
|
||||
AlarmingGroup = [
|
||||
cfg.StrOpt('catalog_type',
|
||||
default='alarming',
|
||||
help="Catalog type of the Alarming service."),
|
||||
cfg.StrOpt('endpoint_type',
|
||||
default='publicURL',
|
||||
choices=['public', 'admin', 'internal',
|
||||
'publicURL', 'adminURL', 'internalURL'],
|
||||
help="The endpoint type to use for the alarming service."),
|
||||
]
|
||||
|
||||
|
||||
telemetry_feature_group = cfg.OptGroup(name='telemetry-feature-enabled',
|
||||
title='Enabled Ceilometer Features')
|
||||
|
||||
TelemetryFeaturesGroup = [
|
||||
cfg.BoolOpt('events',
|
||||
default=False,
|
||||
help="Runs Ceilometer event-related tests"),
|
||||
]
|
||||
|
||||
|
||||
dashboard_group = cfg.OptGroup(name="dashboard",
|
||||
title="Dashboard options")
|
||||
|
||||
@ -1070,12 +1026,6 @@ ServiceAvailableGroup = [
|
||||
cfg.BoolOpt('heat',
|
||||
default=False,
|
||||
help="Whether or not Heat is expected to be available"),
|
||||
cfg.BoolOpt('ceilometer',
|
||||
default=True,
|
||||
help="Whether or not Ceilometer is expected to be available"),
|
||||
cfg.BoolOpt('aodh',
|
||||
default=False,
|
||||
help="Whether or not Aodh is expected to be available"),
|
||||
cfg.BoolOpt('horizon',
|
||||
default=True,
|
||||
help="Whether or not Horizon is expected to be available"),
|
||||
@ -1221,9 +1171,6 @@ _opts = [
|
||||
(object_storage_feature_group, ObjectStoreFeaturesGroup),
|
||||
(database_group, DatabaseGroup),
|
||||
(orchestration_group, OrchestrationGroup),
|
||||
(telemetry_group, TelemetryGroup),
|
||||
(telemetry_feature_group, TelemetryFeaturesGroup),
|
||||
(alarming_group, AlarmingGroup),
|
||||
(dashboard_group, DashboardGroup),
|
||||
(data_processing_group, DataProcessingGroup),
|
||||
(data_processing_feature_group, DataProcessingFeaturesGroup),
|
||||
@ -1292,8 +1239,6 @@ class TempestConfigPrivate(object):
|
||||
'object-storage-feature-enabled']
|
||||
self.database = _CONF.database
|
||||
self.orchestration = _CONF.orchestration
|
||||
self.telemetry = _CONF.telemetry
|
||||
self.telemetry_feature_enabled = _CONF['telemetry-feature-enabled']
|
||||
self.dashboard = _CONF.dashboard
|
||||
self.data_processing = _CONF['data-processing']
|
||||
self.data_processing_feature_enabled = _CONF[
|
||||
|
@ -19,8 +19,7 @@ import pep8
|
||||
|
||||
|
||||
PYTHON_CLIENTS = ['cinder', 'glance', 'keystone', 'nova', 'swift', 'neutron',
|
||||
'trove', 'ironic', 'savanna', 'heat', 'ceilometer',
|
||||
'sahara']
|
||||
'trove', 'ironic', 'savanna', 'heat', 'sahara']
|
||||
|
||||
PYTHON_CLIENT_RE = re.compile('import (%s)client' % '|'.join(PYTHON_CLIENTS))
|
||||
TEST_DEFINITION = re.compile(r'^\s*def test.*')
|
||||
|
@ -1,6 +1,4 @@
|
||||
./tempest/services/object_storage/object_client.py
|
||||
./tempest/services/telemetry/json/alarming_client.py
|
||||
./tempest/services/telemetry/json/telemetry_client.py
|
||||
./tempest/services/volume/base/base_qos_client.py
|
||||
./tempest/services/volume/base/base_backups_client.py
|
||||
./tempest/services/baremetal/base.py
|
||||
|
@ -1,102 +0,0 @@
|
||||
# Copyright 2014 Red Hat
|
||||
#
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from oslo_log import log as logging
|
||||
|
||||
from tempest import config
|
||||
from tempest.scenario import manager
|
||||
from tempest import test
|
||||
|
||||
CONF = config.CONF
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
# Loop for up to 120 seconds waiting on notifications
|
||||
# NOTE(chdent): The choice of 120 seconds is fairly
|
||||
# arbitrary: Long enough to give the notifications the
|
||||
# chance to travel across a highly latent bus but not
|
||||
# so long as to allow excessive latency to never be visible.
|
||||
# TODO(chdent): Ideally this value would come from configuration.
|
||||
NOTIFICATIONS_WAIT = 120
|
||||
NOTIFICATIONS_SLEEP = 1
|
||||
|
||||
|
||||
class TestObjectStorageTelemetry(manager.ObjectStorageScenarioTest):
|
||||
"""Test that swift uses the ceilometer middleware.
|
||||
|
||||
* create container.
|
||||
* upload a file to the created container.
|
||||
* retrieve the file from the created container.
|
||||
* wait for notifications from ceilometer.
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def skip_checks(cls):
|
||||
super(TestObjectStorageTelemetry, cls).skip_checks()
|
||||
if not CONF.service_available.ceilometer:
|
||||
skip_msg = ("%s skipped as ceilometer is not available" %
|
||||
cls.__name__)
|
||||
raise cls.skipException(skip_msg)
|
||||
|
||||
@classmethod
|
||||
def setup_clients(cls):
|
||||
super(TestObjectStorageTelemetry, cls).setup_clients()
|
||||
cls.telemetry_client = cls.os_operator.telemetry_client
|
||||
|
||||
def _confirm_notifications(self, container_name, obj_name):
|
||||
# NOTE: Loop seeking for appropriate notifications about the containers
|
||||
# and objects sent to swift.
|
||||
|
||||
def _check_samples():
|
||||
# NOTE: Return True only if we have notifications about some
|
||||
# containers and some objects and the notifications are about
|
||||
# the expected containers and objects.
|
||||
# Otherwise returning False will case _check_samples to be
|
||||
# called again.
|
||||
results = self.telemetry_client.list_samples(
|
||||
'storage.objects.incoming.bytes')
|
||||
LOG.debug('got samples %s', results)
|
||||
|
||||
# Extract container info from samples.
|
||||
containers, objects = [], []
|
||||
for sample in results:
|
||||
meta = sample['resource_metadata']
|
||||
if meta.get('container') and meta['container'] != 'None':
|
||||
containers.append(meta['container'])
|
||||
elif (meta.get('target.metadata:container') and
|
||||
meta['target.metadata:container'] != 'None'):
|
||||
containers.append(meta['target.metadata:container'])
|
||||
|
||||
if meta.get('object') and meta['object'] != 'None':
|
||||
objects.append(meta['object'])
|
||||
elif (meta.get('target.metadata:object') and
|
||||
meta['target.metadata:object'] != 'None'):
|
||||
objects.append(meta['target.metadata:object'])
|
||||
|
||||
return (container_name in containers and obj_name in objects)
|
||||
|
||||
self.assertTrue(test.call_until_true(_check_samples,
|
||||
NOTIFICATIONS_WAIT,
|
||||
NOTIFICATIONS_SLEEP),
|
||||
'Correct notifications were not received after '
|
||||
'%s seconds.' % NOTIFICATIONS_WAIT)
|
||||
|
||||
@test.idempotent_id('6d6b88e5-3e38-41bc-b34a-79f713a6cb84')
|
||||
@test.services('object_storage', 'telemetry')
|
||||
def test_swift_middleware_notifies(self):
|
||||
container_name = self.create_container()
|
||||
obj_name, _ = self.upload_object_to_container(container_name)
|
||||
self._confirm_notifications(container_name, obj_name)
|
@ -1,98 +0,0 @@
|
||||
# Copyright 2014 OpenStack Foundation
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from oslo_serialization import jsonutils as json
|
||||
from six.moves.urllib import parse as urllib
|
||||
|
||||
from tempest.lib.common import rest_client
|
||||
|
||||
|
||||
class AlarmingClient(rest_client.RestClient):
|
||||
|
||||
version = '2'
|
||||
uri_prefix = "v2"
|
||||
|
||||
def deserialize(self, body):
|
||||
return json.loads(body.replace("\n", ""))
|
||||
|
||||
def serialize(self, body):
|
||||
return json.dumps(body)
|
||||
|
||||
def list_alarms(self, query=None):
|
||||
uri = '%s/alarms' % self.uri_prefix
|
||||
uri_dict = {}
|
||||
if query:
|
||||
uri_dict = {'q.field': query[0],
|
||||
'q.op': query[1],
|
||||
'q.value': query[2]}
|
||||
if uri_dict:
|
||||
uri += "?%s" % urllib.urlencode(uri_dict)
|
||||
resp, body = self.get(uri)
|
||||
self.expected_success(200, resp.status)
|
||||
body = self.deserialize(body)
|
||||
return rest_client.ResponseBodyList(resp, body)
|
||||
|
||||
def show_alarm(self, alarm_id):
|
||||
uri = '%s/alarms/%s' % (self.uri_prefix, alarm_id)
|
||||
resp, body = self.get(uri)
|
||||
self.expected_success(200, resp.status)
|
||||
body = self.deserialize(body)
|
||||
return rest_client.ResponseBody(resp, body)
|
||||
|
||||
def show_alarm_history(self, alarm_id):
|
||||
uri = "%s/alarms/%s/history" % (self.uri_prefix, alarm_id)
|
||||
resp, body = self.get(uri)
|
||||
self.expected_success(200, resp.status)
|
||||
body = self.deserialize(body)
|
||||
return rest_client.ResponseBodyList(resp, body)
|
||||
|
||||
def delete_alarm(self, alarm_id):
|
||||
uri = "%s/alarms/%s" % (self.uri_prefix, alarm_id)
|
||||
resp, body = self.delete(uri)
|
||||
self.expected_success(204, resp.status)
|
||||
if body:
|
||||
body = self.deserialize(body)
|
||||
return rest_client.ResponseBody(resp, body)
|
||||
|
||||
def create_alarm(self, **kwargs):
|
||||
uri = "%s/alarms" % self.uri_prefix
|
||||
body = self.serialize(kwargs)
|
||||
resp, body = self.post(uri, body)
|
||||
self.expected_success(201, resp.status)
|
||||
body = self.deserialize(body)
|
||||
return rest_client.ResponseBody(resp, body)
|
||||
|
||||
def update_alarm(self, alarm_id, **kwargs):
|
||||
uri = "%s/alarms/%s" % (self.uri_prefix, alarm_id)
|
||||
body = self.serialize(kwargs)
|
||||
resp, body = self.put(uri, body)
|
||||
self.expected_success(200, resp.status)
|
||||
body = self.deserialize(body)
|
||||
return rest_client.ResponseBody(resp, body)
|
||||
|
||||
def show_alarm_state(self, alarm_id):
|
||||
uri = "%s/alarms/%s/state" % (self.uri_prefix, alarm_id)
|
||||
resp, body = self.get(uri)
|
||||
self.expected_success(200, resp.status)
|
||||
body = self.deserialize(body)
|
||||
return rest_client.ResponseBodyData(resp, body)
|
||||
|
||||
def alarm_set_state(self, alarm_id, state):
|
||||
uri = "%s/alarms/%s/state" % (self.uri_prefix, alarm_id)
|
||||
body = self.serialize(state)
|
||||
resp, body = self.put(uri, body)
|
||||
self.expected_success(200, resp.status)
|
||||
body = self.deserialize(body)
|
||||
return rest_client.ResponseBodyData(resp, body)
|
@ -1,81 +0,0 @@
|
||||
# Copyright 2014 OpenStack Foundation
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from oslo_serialization import jsonutils as json
|
||||
from six.moves.urllib import parse as urllib
|
||||
|
||||
from tempest.lib.common import rest_client
|
||||
|
||||
|
||||
class TelemetryClient(rest_client.RestClient):
|
||||
|
||||
version = '2'
|
||||
uri_prefix = "v2"
|
||||
|
||||
def deserialize(self, body):
|
||||
return json.loads(body.replace("\n", ""))
|
||||
|
||||
def serialize(self, body):
|
||||
return json.dumps(body)
|
||||
|
||||
def create_sample(self, meter_name, sample_list):
|
||||
uri = "%s/meters/%s" % (self.uri_prefix, meter_name)
|
||||
body = self.serialize(sample_list)
|
||||
resp, body = self.post(uri, body)
|
||||
self.expected_success(200, resp.status)
|
||||
body = self.deserialize(body)
|
||||
return rest_client.ResponseBody(resp, body)
|
||||
|
||||
def _helper_list(self, uri, query=None, period=None):
|
||||
uri_dict = {}
|
||||
if query:
|
||||
uri_dict = {'q.field': query[0],
|
||||
'q.op': query[1],
|
||||
'q.value': query[2]}
|
||||
if period:
|
||||
uri_dict['period'] = period
|
||||
if uri_dict:
|
||||
uri += "?%s" % urllib.urlencode(uri_dict)
|
||||
resp, body = self.get(uri)
|
||||
self.expected_success(200, resp.status)
|
||||
body = self.deserialize(body)
|
||||
return rest_client.ResponseBodyList(resp, body)
|
||||
|
||||
def list_resources(self, query=None):
|
||||
uri = '%s/resources' % self.uri_prefix
|
||||
return self._helper_list(uri, query)
|
||||
|
||||
def list_meters(self, query=None):
|
||||
uri = '%s/meters' % self.uri_prefix
|
||||
return self._helper_list(uri, query)
|
||||
|
||||
def list_statistics(self, meter, period=None, query=None):
|
||||
uri = "%s/meters/%s/statistics" % (self.uri_prefix, meter)
|
||||
return self._helper_list(uri, query, period)
|
||||
|
||||
def list_samples(self, meter_id, query=None):
|
||||
uri = '%s/meters/%s' % (self.uri_prefix, meter_id)
|
||||
return self._helper_list(uri, query)
|
||||
|
||||
def list_events(self, query=None):
|
||||
uri = '%s/events' % self.uri_prefix
|
||||
return self._helper_list(uri, query)
|
||||
|
||||
def show_resource(self, resource_id):
|
||||
uri = '%s/resources/%s' % (self.uri_prefix, resource_id)
|
||||
resp, body = self.get(uri)
|
||||
self.expected_success(200, resp.status)
|
||||
body = self.deserialize(body)
|
||||
return rest_client.ResponseBody(resp, body)
|
@ -78,7 +78,6 @@ def get_service_list():
|
||||
'identity': True,
|
||||
'object_storage': CONF.service_available.swift,
|
||||
'dashboard': CONF.service_available.horizon,
|
||||
'telemetry': CONF.service_available.ceilometer,
|
||||
'data_processing': CONF.service_available.sahara,
|
||||
'database': CONF.service_available.trove
|
||||
}
|
||||
@ -94,7 +93,7 @@ def services(*args):
|
||||
def decorator(f):
|
||||
services = ['compute', 'image', 'baremetal', 'volume', 'orchestration',
|
||||
'network', 'identity', 'object_storage', 'dashboard',
|
||||
'telemetry', 'data_processing', 'database']
|
||||
'data_processing', 'database']
|
||||
for service in args:
|
||||
if service not in services:
|
||||
raise exceptions.InvalidServiceTag('%s is not a valid '
|
||||
|
Loading…
Reference in New Issue
Block a user