Update Heat autoscaling test

Heat OSTF test 'test autoscaling' was updated:
- Added new templates to use Ceilometer autoscaling resources
- Added checks to the test that Ceilometer is installed
- Removed now unnecessary Fedora17 image checks

Now in this test we will check Heat+Ceilometer autoscaling instead
of native one. So it is totally different test.

Closes-Bug: #1361576
Change-Id: I535709f0be8392d5aad988b461f996f43340d252
This commit is contained in:
Anastasia Kuznetsova 2014-11-24 12:31:42 +04:00
parent a35f516f16
commit 52fb4bf568
6 changed files with 218 additions and 362 deletions

View File

@ -1,133 +0,0 @@
heat_template_version: '2013-05-23'
description: AWS CloudFormation Sample Template
parameters:
InstanceType:
type: string
ImageId:
type: string
KeyName:
type: string
SecurityGroup:
type: string
resources:
CfnUser:
type: AWS::IAM::User
AKeys:
type: AWS::IAM::AccessKey
properties:
UserName: {Ref: CfnUser}
AGroup:
type: AWS::AutoScaling::AutoScalingGroup
properties:
AvailabilityZones: {'Fn::GetAZs': ""}
LaunchConfigurationName: {Ref: LaunchConfig}
MinSize: '1'
MaxSize: '2'
VPCZoneIdentifier: []
AScaleUpPolicy:
type: AWS::AutoScaling::ScalingPolicy
properties:
AdjustmentType: ChangeInCapacity
AutoScalingGroupName: {Ref: AGroup}
Cooldown: '60'
ScalingAdjustment: '1'
AScaleDownPolicy:
type: AWS::AutoScaling::ScalingPolicy
properties:
AdjustmentType: ChangeInCapacity
AutoScalingGroupName: {Ref: AGroup}
Cooldown: '60'
ScalingAdjustment: '-1'
CPUAlarmHigh:
type: OS::Heat::CWLiteAlarm
properties:
AlarmDescription: Scale-up if CPU > 50% for 1 minute
MetricName: CPUUtilization
Namespace: system/linux
Statistic: Average
Period: '60'
EvaluationPeriods: '1'
Threshold: '50'
AlarmActions:
- {Ref: AScaleUpPolicy}
Dimensions:
- Name: AutoScalingGroupName
Value: {Ref: AGroup}
ComparisonOperator: GreaterThanThreshold
CPUAlarmLow:
type: OS::Heat::CWLiteAlarm
properties:
AlarmDescription: Scale-down if CPU < 30% for 1 minute
MetricName: CPUUtilization
Namespace: system/linux
Statistic: Average
Period: '60'
EvaluationPeriods: '1'
Threshold: '30'
AlarmActions:
- {Ref: AScaleDownPolicy}
Dimensions:
- Name: AutoScalingGroupName
Value: {Ref: AGroup}
ComparisonOperator: LessThanThreshold
LaunchConfig:
type: AWS::AutoScaling::LaunchConfiguration
metadata:
AWS::CloudFormation::Init:
config:
files:
/etc/cfn/cfn-credentials:
content:
Fn::Join:
- ''
- - AWSAccessKeyId=
- {Ref: AKeys}
- '
'
- AWSSecretKey=
- get_attr: [AKeys, SecretAccessKey]
- '
'
mode: '000400'
owner: root
group: root
/tmp/stats-crontab.txt:
content:
Fn::Join:
- ''
- - 'MAIL=""
'
- '
'
- '* * * * * /opt/aws/bin/cfn-push-stats --watch '
- {Ref: CPUAlarmHigh}
- ' --cpu-util
'
- '* * * * * /opt/aws/bin/cfn-push-stats --watch '
- {Ref: CPUAlarmLow}
- ' --cpu-util
'
mode: '000600'
owner: root
group: root
properties:
ImageId: {Ref: ImageId}
InstanceType: {Ref: InstanceType}
KeyName: {Ref: KeyName}
SecurityGroups: [{Ref: SecurityGroup}]
UserData:
str_replace:
template: |
#!/bin/bash -v
/opt/aws/bin/cfn-init -s $stack_id -r LaunchConfig
# install crontab
crontab /tmp/stats-crontab.txt
touch /tmp/vm_ready.txt
params:
$stack_id: {get_param: "OS::stack_id"}

View File

@ -0,0 +1,76 @@
heat_template_version: 2013-05-23
parameters:
KeyName:
type: string
InstanceType:
type: string
ImageId:
type: string
SecurityGroup:
type: string
Subnet:
type: string
resources:
my_asg:
type: OS::Heat::AutoScalingGroup
properties:
resource:
type: OS::Nova::Server
properties:
metadata: {"metering.stack": {get_param: "OS::stack_id"}}
key_name: { get_param: KeyName }
image: { get_param: ImageId }
flavor: { get_param: InstanceType }
security_groups:
- get_param: SecurityGroup
networks:
- network: {get_param: Subnet}
min_size: 1
max_size: 2
scale_up_policy:
type: OS::Heat::ScalingPolicy
properties:
adjustment_type: change_in_capacity
auto_scaling_group_id: {get_resource: my_asg}
cooldown: 60
scaling_adjustment: 1
scale_down_policy:
type: OS::Heat::ScalingPolicy
properties:
adjustment_type: change_in_capacity
auto_scaling_group_id: {get_resource: my_asg}
cooldown: 60
scaling_adjustment: '-1'
cpu_alarm_high:
type: OS::Ceilometer::Alarm
properties:
description: Scale-up if the average CPU > 50% for 1 minute
meter_name: cpu_util
statistic: avg
period: 60
evaluation_periods: 1
threshold: 50
alarm_actions:
- {get_attr: [scale_up_policy, alarm_url]}
matching_metadata: {'metadata.user_metadata.stack': {get_param: "OS::stack_id"}}
comparison_operator: gt
cpu_alarm_low:
type: OS::Ceilometer::Alarm
properties:
description: Scale-down if the average CPU < 15% for 1 minutes
meter_name: cpu_util
statistic: avg
period: 60
evaluation_periods: 1
threshold: 15
alarm_actions:
- {get_attr: [scale_down_policy, alarm_url]}
matching_metadata: {'metadata.user_metadata.stack': {get_param: "OS::stack_id"}}
comparison_operator: lt

View File

@ -0,0 +1,72 @@
heat_template_version: 2013-05-23
parameters:
KeyName:
type: string
InstanceType:
type: string
ImageId:
type: string
SecurityGroup:
type: string
resources:
my_asg:
type: OS::Heat::AutoScalingGroup
properties:
resource:
type: OS::Nova::Server
properties:
metadata: {"metering.stack": {get_param: "OS::stack_id"}}
key_name: { get_param: KeyName }
image: { get_param: ImageId }
flavor: { get_param: InstanceType }
security_groups:
- get_param: SecurityGroup
min_size: 1
max_size: 2
scale_up_policy:
type: OS::Heat::ScalingPolicy
properties:
adjustment_type: change_in_capacity
auto_scaling_group_id: {get_resource: my_asg}
cooldown: 60
scaling_adjustment: 1
scale_down_policy:
type: OS::Heat::ScalingPolicy
properties:
adjustment_type: change_in_capacity
auto_scaling_group_id: {get_resource: my_asg}
cooldown: 60
scaling_adjustment: '-1'
cpu_alarm_high:
type: OS::Ceilometer::Alarm
properties:
description: Scale-up if the average CPU > 50% for 1 minute
meter_name: cpu_util
statistic: avg
period: 60
evaluation_periods: 1
threshold: 50
alarm_actions:
- {get_attr: [scale_up_policy, alarm_url]}
matching_metadata: {'metadata.user_metadata.stack': {get_param: "OS::stack_id"}}
comparison_operator: gt
cpu_alarm_low:
type: OS::Ceilometer::Alarm
properties:
description: Scale-down if the average CPU < 15% for 1 minutes
meter_name: cpu_util
statistic: avg
period: 60
evaluation_periods: 1
threshold: 15
alarm_actions:
- {get_attr: [scale_down_policy, alarm_url]}
matching_metadata: {'metadata.user_metadata.stack': {get_param: "OS::stack_id"}}
comparison_operator: lt

View File

@ -1,135 +0,0 @@
heat_template_version: '2013-05-23'
description: AWS CloudFormation Sample Template
parameters:
InstanceType:
type: string
ImageId:
type: string
Subnet:
type: string
KeyName:
type: string
SecurityGroup:
type: string
resources:
CfnUser:
type: AWS::IAM::User
AKeys:
type: AWS::IAM::AccessKey
properties:
UserName: {Ref: CfnUser}
AGroup:
type: AWS::AutoScaling::AutoScalingGroup
properties:
AvailabilityZones: {'Fn::GetAZs': ""}
LaunchConfigurationName: {Ref: LaunchConfig}
MinSize: '1'
MaxSize: '2'
VPCZoneIdentifier: [{Ref: Subnet}]
AScaleUpPolicy:
type: AWS::AutoScaling::ScalingPolicy
properties:
AdjustmentType: ChangeInCapacity
AutoScalingGroupName: {Ref: AGroup}
Cooldown: '60'
ScalingAdjustment: '1'
AScaleDownPolicy:
type: AWS::AutoScaling::ScalingPolicy
properties:
AdjustmentType: ChangeInCapacity
AutoScalingGroupName: {Ref: AGroup}
Cooldown: '60'
ScalingAdjustment: '-1'
CPUAlarmHigh:
type: OS::Heat::CWLiteAlarm
properties:
AlarmDescription: Scale-up if CPU > 50% for 1 minute
MetricName: CPUUtilization
Namespace: system/linux
Statistic: Average
Period: '60'
EvaluationPeriods: '1'
Threshold: '50'
AlarmActions:
- {Ref: AScaleUpPolicy}
Dimensions:
- Name: AutoScalingGroupName
Value: {Ref: AGroup}
ComparisonOperator: GreaterThanThreshold
CPUAlarmLow:
type: OS::Heat::CWLiteAlarm
properties:
AlarmDescription: Scale-down if CPU < 30% for 1 minute
MetricName: CPUUtilization
Namespace: system/linux
Statistic: Average
Period: '60'
EvaluationPeriods: '1'
Threshold: '30'
AlarmActions:
- {Ref: AScaleDownPolicy}
Dimensions:
- Name: AutoScalingGroupName
Value: {Ref: AGroup}
ComparisonOperator: LessThanThreshold
LaunchConfig:
type: AWS::AutoScaling::LaunchConfiguration
metadata:
AWS::CloudFormation::Init:
config:
files:
/etc/cfn/cfn-credentials:
content:
Fn::Join:
- ''
- - AWSAccessKeyId=
- {Ref: AKeys}
- '
'
- AWSSecretKey=
- get_attr: [AKeys, SecretAccessKey]
- '
'
mode: '000400'
owner: root
group: root
/tmp/stats-crontab.txt:
content:
Fn::Join:
- ''
- - 'MAIL=""
'
- '
'
- '* * * * * /opt/aws/bin/cfn-push-stats --watch '
- {Ref: CPUAlarmHigh}
- ' --cpu-util
'
- '* * * * * /opt/aws/bin/cfn-push-stats --watch '
- {Ref: CPUAlarmLow}
- ' --cpu-util
'
mode: '000600'
owner: root
group: root
properties:
ImageId: {Ref: ImageId}
InstanceType: {Ref: InstanceType}
KeyName: {Ref: KeyName}
SecurityGroups: [{Ref: SecurityGroup}]
UserData:
str_replace:
template: |
#!/bin/bash -v
/opt/aws/bin/cfn-init -s $stack_id -r LaunchConfig
# install crontab
crontab /tmp/stats-crontab.txt
touch /tmp/vm_ready.txt
params:
$stack_id: {get_param: "OS::stack_id"}

View File

@ -129,10 +129,6 @@ class HeatBaseTest(fuel_health.nmanager.NovaNetworkScenarioTest):
self.wait_interval):
self.fail("Timed out waiting for stack to be deleted.")
def _find_heat_image(self, image_name):
return image_name in [i.name for i in
self.compute_client.images.list()]
def _wait_for_autoscaling(self, exp_count,
timeout, interval, reduced_stack_name):
LOG.info('expected count is {0}'.format(exp_count))
@ -151,13 +147,14 @@ class HeatBaseTest(fuel_health.nmanager.NovaNetworkScenarioTest):
return fuel_health.test.call_until_true(
count_instances, timeout, interval, reduced_stack_name)
def _wait_for_cloudinit(self, conn_string, timeout, interval):
def _wait_for_vm_ready_for_load(self, conn_string, timeout, interval):
"""
Wait for fake file (described in the stack template) to be created
on the instance to make sure cloud-init procedure is completed.
Wait for fake file to be created on the instance
to make sure that vm is ready.
"""
cmd = (conn_string +
" test -f /tmp/vm_ready.txt && echo -ne YES || echo -ne NO")
" 'touch /tmp/ostf-heat.txt; "
"test -f /tmp/ostf-heat.txt && echo -ne YES || echo -ne NO'")
def check():
return self._run_ssh_cmd(cmd)[0] == "YES"
@ -167,19 +164,23 @@ class HeatBaseTest(fuel_health.nmanager.NovaNetworkScenarioTest):
def _save_key_to_file(self, key):
return self._run_ssh_cmd(
"KEY=`mktemp`; echo '%s' > $KEY; echo -ne $KEY;" % key)[0]
"KEY=`mktemp`; echo '%s' > $KEY; "
"chmod 600 $KEY; echo -ne $KEY;" % key)[0]
def _delete_key_file(self, filepath):
self._run_ssh_cmd("rm -f %s" % filepath)
def _load_vm_cpu(self, connection_string):
return self._run_ssh_cmd(
connection_string + " cat /dev/urandom | gzip -9 > /dev/null &")[0]
self._run_ssh_cmd(connection_string + " 'rm -f /tmp/ostf-heat.txt'")
return self._run_ssh_cmd(connection_string +
" 'cat /dev/urandom |"
" gzip -9 > /dev/null &'")[0]
def _release_vm_cpu(self, connection_string):
pid = self._run_ssh_cmd(connection_string +
" ps -ef | grep \"cat /dev/urandom\" "
"| grep -v grep | awk '{print $2}'")[0]
' ps -ef | grep \"cat /dev/urandom\" '
'| grep -v grep | awk \"{print $1}\"')[0]
return self._run_ssh_cmd(connection_string +
" kill -9 %s" % pid.strip())[0]

View File

@ -15,7 +15,6 @@
import logging
from fuel_health import heatmanager
from fuel_health.common.utils import data_utils
LOG = logging.getLogger(__name__)
@ -24,9 +23,6 @@ LOG = logging.getLogger(__name__)
class HeatSmokeTests(heatmanager.HeatBaseTest):
"""
Test class verifies Heat API calls, rollback and autoscaling use-cases.
Special requirements:
1. Fedora-17 image with pre-installed cfntools and cloud-init packages
should be imported.
"""
def setUp(self):
super(HeatSmokeTests, self).setUp()
@ -201,86 +197,67 @@ class HeatSmokeTests(heatmanager.HeatBaseTest):
Target component: Heat
Scenario:
1. Check that image with cfntools package is imported.
2. Create a flavor.
3. Create a keypair.
4. Save generated private key to file on Controller node.
5. Create a security group.
6. Create a stack.
7. Wait for the stack status to change to 'CREATE_COMPLETE'.
8. Create a floating ip.
9. Assign the floating ip to the instance of the stack.
10. Wait for cloud_init procedure to be completed on the instance.
11. Load the instance CPU to initiate the stack scaling up.
12. Wait for the 2nd instance to be launched.
13. Release the instance CPU to initiate the stack scaling down.
14. Wait for the 2nd instance to be terminated.
15. Delete the file with private key.
16. Delete the stack.
17. Wait for the stack to be deleted.
Duration: 3000 s.
1. Create a keypair.
2. Save generated private key to file on Controller node.
3. Create a security group.
4. Create a stack.
5. Wait for the stack status to change to 'CREATE_COMPLETE'.
6. Create a floating IP.
7. Assign the floating IP to the instance of the stack.
8. Wait for instance is ready for load.
9. Load the instance CPU to initiate the stack scaling up.
10. Wait for the 2nd instance to be launched.
11. Release the instance CPU to initiate the stack scaling down.
12. Wait for the 2nd instance to be terminated.
13. Delete the file with private key.
14. Delete the stack.
15. Wait for the stack to be deleted.
Duration: 2100 s.
"""
msg = ("Autoscaling with native cloudwatch mechanism does "
"not work in Heat when used multi-engine architecture.")
if not self.ceilometer_client:
self.skipTest("This test can't be run in current configuration. "
"It checks Heat autoscaling using "
"Ceilometer resources, so Ceilometer "
"should be installed.")
if 'ha' in self.config.mode:
LOG.debug(msg)
self.skipTest(msg)
self.check_image_exists()
image_name = "F17-x86_64-cfntools"
msg = ("Image with cfntools package wasn't "
"imported into Glance, please check "
"http://docs.mirantis.com/openstack/fuel/fuel"
"-5.0/user-guide.html#platform-tests-description")
image_available = self._find_heat_image(image_name)
if not image_available:
LOG.debug(msg)
self.skipTest(msg)
flavor_name = data_utils.rand_name('ostf-heat-flavor-')
flavor = self.verify(10, self.compute_client.flavors.create, 2,
"Flavor can not be created.", "flavor creation",
flavor_name, 512, 1, 12)
self.flavors.append(flavor)
keypair = self.verify(10, self._create_keypair, 3,
keypair = self.verify(10, self._create_keypair, 1,
'Keypair can not be created.',
'keypair creation',
self.compute_client)
path_to_key = self.verify(10, self._save_key_to_file, 4,
path_to_key = self.verify(10, self._save_key_to_file, 2,
"Private key can not be saved to file.",
"saving private key to the file",
keypair.private_key)
sec_group = self.verify(10, self._create_security_group, 5,
sec_group = self.verify(10, self._create_security_group, 3,
'Security group can not be created.',
'security group creation',
self.compute_client, 'ost1_test-sgroup')
parameters = {
"KeyName": keypair.name,
"InstanceType": flavor.name,
"ImageId": image_name,
"InstanceType": self.testvm_flavor.name,
"ImageId": self.config.compute.image_name,
"SecurityGroup": sec_group.name
}
if 'neutron' in self.config.network.network_provider:
parameters['Subnet'] = self._get_subnet_id()
template = self._load_template('heat_autoscaling_template.yaml')
else:
template = self._load_template('heat_autoscale_nova.yaml')
# create stack
if 'neutron' in self.config.network.network_provider:
parameters['Subnet'] = self.private_net
template = self._load_template('heat_autoscaling_neutron.yaml')
else:
template = self._load_template('heat_autoscaling_nova.yaml')
fail_msg = "Stack was not created properly."
stack = self.verify(20, self._create_stack, 6,
stack = self.verify(20, self._create_stack, 4,
fail_msg, "stack creation",
self.heat_client, template,
parameters=parameters)
self.verify(600, self._wait_for_stack_status, 7,
self.verify(600, self._wait_for_stack_status, 5,
fail_msg,
"stack status becoming 'CREATE_COMPLETE'",
stack.id, 'CREATE_COMPLETE', 600, 15)
@ -291,7 +268,7 @@ class HeatSmokeTests(heatmanager.HeatBaseTest):
# find just created instance
instance_list = self.compute_client.servers.list()
LOG.info('servers list is {0}'.format(instance_list))
LOG.info('expected img_name starts with {0}'.format(
LOG.info('expected instance name starts with {0}'.format(
reduced_stack_name))
for server in instance_list:
@ -300,63 +277,61 @@ class HeatSmokeTests(heatmanager.HeatBaseTest):
self.instance.append(server)
if not self.instance:
self.fail("Failed step: 7 Instance for the {0} stack "
self.fail("Failed step: 5 Instance for the {0} stack "
"was not created.".format(self.instance))
floating_ip = self.verify(10, self._create_floating_ip, 8,
floating_ip = self.verify(10, self._create_floating_ip, 6,
"Floating IP can not be created.",
'floating IP creation')
self.verify(10, self._assign_floating_ip_to_instance, 9,
self.verify(10, self._assign_floating_ip_to_instance, 7,
"Floating IP can not be assigned.",
'assigning floating IP',
self.compute_client, self.instance[0], floating_ip)
vm_connection = "ssh -o StrictHostKeyChecking=no -i %s %s@%s" % (
path_to_key, "ec2-user", floating_ip.ip)
path_to_key, "cirros", floating_ip.ip)
self.verify(1000, self._wait_for_cloudinit, 10,
"Cloud-init script cannot finish within timeout.",
"cloud-init script execution on VM",
vm_connection, 1000, 15)
self.verify(120, self._wait_for_vm_ready_for_load, 8,
"VM is not ready or connection can't be established",
"test script execution on VM",
vm_connection, 120, 15)
self.verify(60, self._load_vm_cpu, 11,
self.verify(60, self._load_vm_cpu, 9,
"Cannot create a process to load VM CPU.",
"loading VM CPU",
vm_connection)
self.verify(500,
self._wait_for_autoscaling, 12,
self.verify(480,
self._wait_for_autoscaling, 10,
"Stack failed to launch the 2nd instance "
"per autoscaling alarm.",
"launching the new instance per autoscaling alarm",
len(self.instance) + 1, 500, 10, reduced_stack_name)
len(self.instance) + 1, 480, 10, reduced_stack_name)
self.verify(180, self._release_vm_cpu, 13,
self.verify(180, self._release_vm_cpu, 11,
"Cannot kill the process on VM to turn CPU load off.",
"turning off VM CPU load",
vm_connection)
self.verify(500, self._wait_for_autoscaling, 14,
self.verify(480, self._wait_for_autoscaling, 12,
"Stack failed to terminate the 2nd instance "
"per autoscaling alarm.",
"terminating the 2nd instance per autoscaling alarm",
len(self.instance), 500, 10, reduced_stack_name)
len(self.instance), 480, 10, reduced_stack_name)
# delete private key file
self.verify(10, self._delete_key_file, 15,
self.verify(10, self._delete_key_file, 13,
"The file with private key cannot be deleted.",
"deleting the file with private key",
path_to_key)
fail_msg = "Cannot delete stack."
self.verify(20, self.heat_client.stacks.delete, 16,
fail_msg,
self.verify(20, self.heat_client.stacks.delete, 14,
"Cannot delete stack.",
"deleting stack",
stack.id)
self.verify(100, self._wait_for_stack_deleted, 17,
fail_msg,
self.verify(100, self._wait_for_stack_deleted, 15,
"Cannot delete stack.",
"deleting stack",
stack.id)