Add basic Ceilometer alarm test
This sends a manual ceilometer sample to trigger the alarm, then confirms that the autoscale policy/group reacts correctly. Note: this doesn't used ScenarioBaseTest as it skips the test unnecessarily on unused images and networks. Change-Id: I5c842779d90497ba88df66bbfd8f447679645192 Depends-On: Ib3795bcca9d5ec3d68c6443a9854dbc56118ca40
This commit is contained in:
@@ -12,6 +12,7 @@
|
|||||||
|
|
||||||
import os
|
import os
|
||||||
|
|
||||||
|
import ceilometerclient.client
|
||||||
import cinderclient.client
|
import cinderclient.client
|
||||||
import heatclient.client
|
import heatclient.client
|
||||||
import keystoneclient.exceptions
|
import keystoneclient.exceptions
|
||||||
@@ -30,6 +31,7 @@ class ClientManager(object):
|
|||||||
CINDERCLIENT_VERSION = '1'
|
CINDERCLIENT_VERSION = '1'
|
||||||
HEATCLIENT_VERSION = '1'
|
HEATCLIENT_VERSION = '1'
|
||||||
NOVACLIENT_VERSION = '2'
|
NOVACLIENT_VERSION = '2'
|
||||||
|
CEILOMETER_VERSION = '2'
|
||||||
|
|
||||||
def __init__(self, conf):
|
def __init__(self, conf):
|
||||||
self.conf = conf
|
self.conf = conf
|
||||||
@@ -39,6 +41,7 @@ class ClientManager(object):
|
|||||||
self.network_client = self._get_network_client()
|
self.network_client = self._get_network_client()
|
||||||
self.volume_client = self._get_volume_client()
|
self.volume_client = self._get_volume_client()
|
||||||
self.object_client = self._get_object_client()
|
self.object_client = self._get_object_client()
|
||||||
|
self.metering_client = self._get_metering_client()
|
||||||
|
|
||||||
def _get_orchestration_client(self):
|
def _get_orchestration_client(self):
|
||||||
region = self.conf.region
|
region = self.conf.region
|
||||||
@@ -136,3 +139,27 @@ class ClientManager(object):
|
|||||||
'insecure': dscv,
|
'insecure': dscv,
|
||||||
}
|
}
|
||||||
return swiftclient.client.Connection(**args)
|
return swiftclient.client.Connection(**args)
|
||||||
|
|
||||||
|
def _get_metering_client(self):
|
||||||
|
dscv = self.conf.disable_ssl_certificate_validation
|
||||||
|
|
||||||
|
keystone = self._get_identity_client()
|
||||||
|
endpoint = keystone.service_catalog.url_for(
|
||||||
|
attr='region',
|
||||||
|
filter_value=self.conf.region,
|
||||||
|
service_type='metering',
|
||||||
|
endpoint_type='publicURL')
|
||||||
|
|
||||||
|
args = {
|
||||||
|
'username': self.conf.username,
|
||||||
|
'password': self.conf.password,
|
||||||
|
'tenant_name': self.conf.tenant_name,
|
||||||
|
'auth_url': self.conf.auth_url,
|
||||||
|
'insecure': dscv,
|
||||||
|
'region_name': self.conf.region,
|
||||||
|
'endpoint_type': 'publicURL',
|
||||||
|
'service_type': 'metering',
|
||||||
|
}
|
||||||
|
|
||||||
|
return ceilometerclient.client.Client(self.CEILOMETER_VERSION,
|
||||||
|
endpoint, **args)
|
||||||
|
|||||||
@@ -87,6 +87,7 @@ class HeatIntegrationTest(testscenarios.WithScenarios,
|
|||||||
self.network_client = self.manager.network_client
|
self.network_client = self.manager.network_client
|
||||||
self.volume_client = self.manager.volume_client
|
self.volume_client = self.manager.volume_client
|
||||||
self.object_client = self.manager.object_client
|
self.object_client = self.manager.object_client
|
||||||
|
self.metering_client = self.manager.metering_client
|
||||||
self.useFixture(fixtures.FakeLogger(format=_LOG_FORMAT))
|
self.useFixture(fixtures.FakeLogger(format=_LOG_FORMAT))
|
||||||
self.updated_time = {}
|
self.updated_time = {}
|
||||||
|
|
||||||
|
|||||||
@@ -16,6 +16,8 @@
|
|||||||
|
|
||||||
localrc_path=$BASE/new/devstack/localrc
|
localrc_path=$BASE/new/devstack/localrc
|
||||||
localconf=$BASE/new/devstack/local.conf
|
localconf=$BASE/new/devstack/local.conf
|
||||||
|
|
||||||
|
echo "CEILOMETER_PIPELINE_INTERVAL=60" >> $localrc_path
|
||||||
echo "HEAT_ENABLE_ADOPT_ABANDON=True" >> $localrc_path
|
echo "HEAT_ENABLE_ADOPT_ABANDON=True" >> $localrc_path
|
||||||
echo -e '[[post-config|$HEAT_CONF]]\n[DEFAULT]\n' >> $localconf
|
echo -e '[[post-config|$HEAT_CONF]]\n[DEFAULT]\n' >> $localconf
|
||||||
echo -e 'notification_driver=messagingv2\n' >> $localconf
|
echo -e 'notification_driver=messagingv2\n' >> $localconf
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ oslo.messaging>=1.8.0,<1.9.0 # Apache-2.0
|
|||||||
oslo.config>=1.9.3,<1.10.0 # Apache-2.0
|
oslo.config>=1.9.3,<1.10.0 # Apache-2.0
|
||||||
oslo.utils>=1.4.0,<1.5.0 # Apache-2.0
|
oslo.utils>=1.4.0,<1.5.0 # Apache-2.0
|
||||||
paramiko>=1.13.0
|
paramiko>=1.13.0
|
||||||
|
python-ceilometerclient>=1.0.13
|
||||||
python-cinderclient>=1.1.0
|
python-cinderclient>=1.1.0
|
||||||
python-keystoneclient>=1.1.0
|
python-keystoneclient>=1.1.0
|
||||||
python-heatclient>=0.3.0
|
python-heatclient>=0.3.0
|
||||||
|
|||||||
@@ -0,0 +1,33 @@
|
|||||||
|
heat_template_version: 2013-05-23
|
||||||
|
resources:
|
||||||
|
asg:
|
||||||
|
type: OS::Heat::AutoScalingGroup
|
||||||
|
properties:
|
||||||
|
max_size: 5
|
||||||
|
min_size: 1
|
||||||
|
resource:
|
||||||
|
type: OS::Heat::RandomString
|
||||||
|
scaleup_policy:
|
||||||
|
type: OS::Heat::ScalingPolicy
|
||||||
|
properties:
|
||||||
|
adjustment_type: change_in_capacity
|
||||||
|
auto_scaling_group_id: {get_resource: asg}
|
||||||
|
cooldown: 0
|
||||||
|
scaling_adjustment: 1
|
||||||
|
alarm:
|
||||||
|
type: OS::Ceilometer::Alarm
|
||||||
|
properties:
|
||||||
|
description: Scale-up if the average CPU > 50% for 1 minute
|
||||||
|
meter_name: test_meter
|
||||||
|
statistic: count
|
||||||
|
comparison_operator: ge
|
||||||
|
threshold: 1
|
||||||
|
period: 60
|
||||||
|
evaluation_periods: 1
|
||||||
|
alarm_actions:
|
||||||
|
- {get_attr: [scaleup_policy, alarm_url]}
|
||||||
|
matching_metadata:
|
||||||
|
metadata.metering.stack_id: {get_param: "OS::stack_id"}
|
||||||
|
outputs:
|
||||||
|
asg_size:
|
||||||
|
value: {get_attr: [asg, current_size]}
|
||||||
57
heat_integrationtests/scenario/test_ceilometer_alarm.py
Normal file
57
heat_integrationtests/scenario/test_ceilometer_alarm.py
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
# 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 heat_integrationtests.common import test
|
||||||
|
|
||||||
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
class CeilometerAlarmTest(test.HeatIntegrationTest):
|
||||||
|
"""Class is responsible for testing of ceilometer usage."""
|
||||||
|
def setUp(self):
|
||||||
|
super(CeilometerAlarmTest, self).setUp()
|
||||||
|
self.client = self.orchestration_client
|
||||||
|
self.template = self._load_template(__file__,
|
||||||
|
'test_ceilometer_alarm.yaml',
|
||||||
|
'templates')
|
||||||
|
|
||||||
|
def check_instance_count(self, stack_identifier, expected):
|
||||||
|
stack = self.client.stacks.get(stack_identifier)
|
||||||
|
actual = self._stack_output(stack, 'asg_size')
|
||||||
|
if actual != expected:
|
||||||
|
LOG.warn('check_instance_count exp:%d, act:%s' % (expected,
|
||||||
|
actual))
|
||||||
|
return actual == expected
|
||||||
|
|
||||||
|
def test_alarm(self):
|
||||||
|
"""Confirm we can create an alarm and trigger it."""
|
||||||
|
|
||||||
|
# 1. create the stack
|
||||||
|
stack_identifier = self.stack_create(template=self.template)
|
||||||
|
|
||||||
|
# 2. send ceilometer a metric (should cause the alarm to fire)
|
||||||
|
sample = {}
|
||||||
|
sample['counter_type'] = 'gauge'
|
||||||
|
sample['counter_name'] = 'test_meter'
|
||||||
|
sample['counter_volume'] = 1
|
||||||
|
sample['counter_unit'] = 'count'
|
||||||
|
sample['resource_metadata'] = {'metering.stack_id':
|
||||||
|
stack_identifier.split('/')[-1]}
|
||||||
|
sample['resource_id'] = 'shouldnt_matter'
|
||||||
|
self.metering_client.samples.create(**sample)
|
||||||
|
|
||||||
|
# 3. confirm we get a scaleup.
|
||||||
|
# Note: there is little point waiting more than 60s+time to scale up.
|
||||||
|
self.assertTrue(test.call_until_true(
|
||||||
|
120, 2, self.check_instance_count, stack_identifier, 2))
|
||||||
Reference in New Issue
Block a user