72a1f72736
Change-Id: I96763dfbfe87dae63c1f99b985014957108ac2ef
289 lines
12 KiB
Python
289 lines
12 KiB
Python
# Copyright 2016 Mirantis, Inc.
|
|
#
|
|
# 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 datetime
|
|
|
|
import ceilometerclient.v2.client
|
|
from fuelweb_test.helpers import checkers as fuelweb_checkers
|
|
from fuelweb_test import logger
|
|
|
|
from stacklight_tests import base_test
|
|
from stacklight_tests.helpers import checkers
|
|
from stacklight_tests.helpers import helpers
|
|
from stacklight_tests.influxdb_grafana.api import InfluxdbPluginApi
|
|
from stacklight_tests.openstack_telemetry import plugin_settings
|
|
|
|
|
|
class OpenstackTelemeteryPluginApi(base_test.PluginApi):
|
|
def __init__(self):
|
|
super(OpenstackTelemeteryPluginApi, self).__init__()
|
|
self._ceilometer = None
|
|
|
|
@property
|
|
def ceilometer_client(self):
|
|
if self._ceilometer is None:
|
|
keystone_access = self.helpers.os_conn.keystone_access
|
|
endpoint = keystone_access.service_catalog.url_for(
|
|
service_type='metering', service_name='ceilometer',
|
|
interface='internal')
|
|
if not endpoint:
|
|
raise self.helpers.NotFound(
|
|
"Cannot find Ceilometer endpoint")
|
|
aodh_endpoint = keystone_access.service_catalog.url_for(
|
|
service_type='alarming', service_name='aodh',
|
|
interface='internal')
|
|
if not aodh_endpoint:
|
|
raise self.helpers.NotFound(
|
|
"Cannot find AODH (alarm) endpoint")
|
|
auth_url = keystone_access.service_catalog.url_for(
|
|
service_type='identity', service_name='keystone',
|
|
interface='internal')
|
|
if not auth_url:
|
|
raise self.helpers.NotFound(
|
|
"Cannot find Keystone endpoint")
|
|
|
|
self._ceilometer = ceilometerclient.v2.Client(
|
|
aodh_endpoint=aodh_endpoint,
|
|
auth_url=auth_url,
|
|
endpoint=endpoint,
|
|
token=lambda: keystone_access.auth_token)
|
|
return self._ceilometer
|
|
|
|
def get_plugin_settings(self):
|
|
return plugin_settings
|
|
|
|
def prepare_plugin(self):
|
|
self.helpers.prepare_plugin(self.settings.plugin_path)
|
|
|
|
def activate_plugin(self, options=None):
|
|
if options is None:
|
|
options = self.settings.default_options
|
|
self.helpers.activate_plugin(
|
|
self.settings.name, self.settings.version, options)
|
|
|
|
def is_kafka_enabled(self):
|
|
return (
|
|
self.fuel_web.get_nailgun_cluster_nodes_by_roles(
|
|
self.helpers.cluster_id, ["kafka"])
|
|
)
|
|
|
|
def check_services_on_nodes(self, services, node_role):
|
|
node_ips = [
|
|
node["ip"] for node in
|
|
self.fuel_web.get_nailgun_cluster_nodes_by_roles(
|
|
self.helpers.cluster_id, [node_role])]
|
|
logger.info("Check {} services on {} nodes".format(
|
|
services, node_role))
|
|
for ip in node_ips:
|
|
for service in services:
|
|
fuelweb_checkers.verify_service(
|
|
ip, service, ignore_count_of_proccesses=True)
|
|
|
|
def check_plugin_online(self):
|
|
non_ha_pcmk_resources = ["p_ceilometer-agent-central",
|
|
"p_aodh-evaluator"]
|
|
ha_pcmk_resources = ["telemetry-collector-heka"]
|
|
controller_services = ["ceilometer-agent-notification",
|
|
"ceilometer-api", "aodh-api"]
|
|
compute_services = ["ceilometer-polling"]
|
|
if self.is_kafka_enabled():
|
|
kafka_services = ["telemetry-collector-hindsight"]
|
|
self.check_services_on_nodes(kafka_services, "kafka")
|
|
ha_pcmk_resources = non_ha_pcmk_resources
|
|
else:
|
|
logger.info("Check {} pacemaker resources".format(
|
|
non_ha_pcmk_resources))
|
|
for resource in non_ha_pcmk_resources:
|
|
self.helpers.check_pacemaker_resource(
|
|
resource, "controller", is_ha=False)
|
|
logger.info(
|
|
"Check {} pacemaker resources".format(ha_pcmk_resources))
|
|
for resource in ha_pcmk_resources:
|
|
self.helpers.check_pacemaker_resource(resource, "controller")
|
|
self.check_services_on_nodes(controller_services, "controller")
|
|
self.check_services_on_nodes(compute_services, "compute")
|
|
logger.info("Check Ceilometer API")
|
|
keystone_access = self.helpers.os_conn.keystone_access
|
|
endpoint = keystone_access.service_catalog.url_for(
|
|
service_type="metering", service_name="ceilometer",
|
|
interface="internal")
|
|
if not endpoint:
|
|
raise helpers.NotFound("Cannot find Ceilometer endpoint")
|
|
headers = {
|
|
"X-Auth-Token": keystone_access.auth_token,
|
|
"content-type": "application/json"
|
|
}
|
|
checkers.check_http_get_response("{}/v2/capabilities".format(endpoint),
|
|
headers=headers)
|
|
logger.info("Check Ceilometer database in InfluxDB")
|
|
InfluxdbPluginApi().do_influxdb_query(
|
|
"show measurements", db="ceilometer")
|
|
|
|
def uninstall_plugin(self):
|
|
return self.helpers.uninstall_plugin(self.settings.name,
|
|
self.settings.version)
|
|
|
|
def check_uninstall_failure(self):
|
|
return self.helpers.check_plugin_cannot_be_uninstalled(
|
|
self.settings.name, self.settings.version)
|
|
|
|
def check_ceilometer_sample_functionality(self):
|
|
logger.info("Start checking Ceilometer Samples API")
|
|
|
|
fail_msg = "Failed to get sample list."
|
|
msg = "getting samples list"
|
|
self.helpers.verify(60, self.ceilometer_client.new_samples.list, 1,
|
|
fail_msg, msg, limit=10)
|
|
|
|
fail_msg = "Failed to get statistic of metric."
|
|
msg = "getting statistic of metric"
|
|
an_hour_ago = (datetime.datetime.now() -
|
|
datetime.timedelta(hours=1)).isoformat()
|
|
query = [{"field": "timestamp", "op": "gt", "value": an_hour_ago}]
|
|
|
|
self.helpers.verify(600, self.ceilometer_client.statistics.list, 2,
|
|
fail_msg, msg, meter_name="image", q=query)
|
|
|
|
def check_ceilometer_alarm_functionality(self):
|
|
logger.info("Start checking Ceilometer AODH(Alarms) API")
|
|
|
|
fail_msg = "Failed to create alarm."
|
|
msg = "creating alarm"
|
|
alarm = self.helpers.verify(60, self.create_alarm, 1, fail_msg, msg,
|
|
meter_name="image",
|
|
threshold=0.9,
|
|
name="ceilometer-fake-alarm",
|
|
period=600,
|
|
statistic="avg",
|
|
comparison_operator="lt")
|
|
|
|
fail_msg = "Failed to get alarm."
|
|
msg = "getting alarm"
|
|
self.helpers.verify(60, self.ceilometer_client.alarms.get, 2,
|
|
fail_msg, msg, alarm_id=alarm.alarm_id)
|
|
|
|
fail_msg = "Failed while waiting for alarm state to become 'ok'."
|
|
msg = "waiting for alarm state to become 'ok'"
|
|
self.helpers.verify(1000, self.check_alarm_state, 3,
|
|
fail_msg, msg, alarm_id=alarm.alarm_id, state="ok")
|
|
|
|
fail_msg = "Failed to update alarm."
|
|
msg = "updating alarm"
|
|
self.helpers.verify(60, self.ceilometer_client.alarms.update, 4,
|
|
fail_msg, msg, alarm_id=alarm.alarm_id,
|
|
threshold=1.1)
|
|
|
|
fail_msg = "Failed while waiting for alarm state to become 'alarm'."
|
|
msg = "waiting for alarm state to become 'alarm'"
|
|
self.helpers.verify(1000, self.check_alarm_state, 5,
|
|
fail_msg, msg, alarm_id=alarm.alarm_id,
|
|
state="alarm")
|
|
|
|
fail_msg = "Failed to get alarm history."
|
|
msg = "getting alarm history"
|
|
self.helpers.verify(60, self.ceilometer_client.alarms.get_history, 6,
|
|
fail_msg, msg, alarm_id=alarm.alarm_id)
|
|
|
|
fail_msg = "Failed to delete alarm."
|
|
msg = "deleting alarm"
|
|
self.helpers.verify(60, self.ceilometer_client.alarms.delete, 7,
|
|
fail_msg, msg, alarm_id=alarm.alarm_id)
|
|
|
|
def check_ceilometer_event_functionality(self):
|
|
logger.info("Start checking Ceilometer Events API")
|
|
|
|
fail_msg = "Failed to get event list."
|
|
msg = "getting event list"
|
|
events_list = self.helpers.verify(
|
|
600, self.ceilometer_client.events.list, 1, fail_msg, msg,
|
|
limit=10
|
|
)
|
|
event_type = events_list[0].event_type
|
|
message_id = events_list[0].message_id
|
|
traits = events_list[0].traits
|
|
|
|
fail_msg = ("Failed to find '{event_type}' event type in certain "
|
|
"'{message_id}' event.".format(event_type=event_type,
|
|
message_id=message_id))
|
|
msg = ("searching '{event_type}' event type in certain "
|
|
"'{message_id}' event.".format(event_type=event_type,
|
|
message_id=message_id))
|
|
self.helpers.verify(60, self.ceilometer_client.events.get, 2, fail_msg,
|
|
msg, message_id=message_id)
|
|
|
|
fail_msg = "Failed to get event types list."
|
|
msg = "getting event types list"
|
|
self.helpers.verify(60, self.ceilometer_client.event_types.list, 3,
|
|
fail_msg, msg)
|
|
|
|
fail_msg = "Failed to get trait list."
|
|
msg = "getting trait list"
|
|
self.helpers.verify(60, self.ceilometer_client.traits.list, 4,
|
|
fail_msg, msg, event_type=event_type,
|
|
trait_name=traits[0]["name"])
|
|
|
|
fail_msg = "Failed to check event traits description."
|
|
msg = "checking event traits description"
|
|
self.helpers.verify(60, self.ceilometer_client.trait_descriptions.list,
|
|
5, fail_msg, msg, event_type=event_type)
|
|
|
|
def check_ceilometer_resource_functionality(self):
|
|
logger.info("Start checking Ceilometer Resource API")
|
|
|
|
fail_msg = "Failed to get resource list."
|
|
msg = "getting resources list"
|
|
resources_list = self.helpers.verify(
|
|
600, self.ceilometer_client.resources.list, 1, fail_msg, msg,
|
|
limit=10)
|
|
for resource in resources_list:
|
|
# We need to check that resource_id doesn't contain char '/'
|
|
# because if it is GET resource request fails
|
|
if "/" not in resource.resource_id:
|
|
resource_id = resource.resource_id
|
|
break
|
|
fail_msg = ("Failed to find '{}' resource with certain resource "
|
|
"ID.".format(resource_id))
|
|
msg = ("searching '{}' resource with certain resource "
|
|
"ID".format(resource_id))
|
|
self.helpers.verify(60, self.ceilometer_client.resources.get, 2,
|
|
fail_msg, msg, resource_id=resource_id)
|
|
|
|
fail_msg = "Failed to get meters list."
|
|
msg = "getting meters list"
|
|
self.helpers.verify(60, self.ceilometer_client.meters.list, 3,
|
|
fail_msg, msg, limit=10)
|
|
|
|
fail_msg = "Failed to get unique meters list."
|
|
msg = "getting unique meters list"
|
|
self.helpers.verify(60, self.ceilometer_client.meters.list, 4,
|
|
fail_msg, msg, limit=10, unique=True)
|
|
|
|
def create_alarm(self, **kwargs):
|
|
for alarm in self.ceilometer_client.alarms.list():
|
|
if alarm.name == kwargs['name']:
|
|
self.ceilometer_client.alarms.delete(alarm.alarm_id)
|
|
return self.ceilometer_client.alarms.create(**kwargs)
|
|
|
|
def check_alarm_state(self, alarm_id, state=None):
|
|
try:
|
|
alarm_state = self.ceilometer_client.alarms.get_state(
|
|
alarm_id)
|
|
except Exception:
|
|
alarm_state = None
|
|
if state:
|
|
if alarm_state == state:
|
|
return True
|
|
elif alarm_state == 'alarm' or 'ok':
|
|
return True
|
|
return False
|