Remove potential co-gating integration tests

This patch propose to use heat tempest plugin for potential
co-gating integration tests.
These tests are consider as potential co-gating. And we now
already maintain them in heat tempest plugin.

This also disables all except two of the gate/test jobs, to enable us to
land this series and stop the carnage. The jobs will be re-enabled once
all of the duplicated tests have been eliminated.

Change-Id: I55e204b72cd5a2876576852b10ad09f24d04beb4
This commit is contained in:
ricolin 2017-12-17 23:29:26 +08:00 committed by Zane Bitter
parent 2c0797b73e
commit ba86129965
17 changed files with 5 additions and 858 deletions

View File

@ -117,14 +117,8 @@
- grenade-heat-multinode - grenade-heat-multinode
- heat-functional-orig-mysql-lbaasv2 - heat-functional-orig-mysql-lbaasv2
- heat-functional-convg-mysql-lbaasv2 - heat-functional-convg-mysql-lbaasv2
- heat-functional-convg-mysql-lbaasv2-amqp1
- heat-functional-convg-mysql-lbaasv2-non-apache
- heat-functional-convg-mysql-lbaasv2-py35
- heat-functional-convg-mysql-lbaasv2-identity-v3-only
gate: gate:
jobs: jobs:
- grenade-heat - grenade-heat
- heat-functional-orig-mysql-lbaasv2 - heat-functional-orig-mysql-lbaasv2
- heat-functional-convg-mysql-lbaasv2 - heat-functional-convg-mysql-lbaasv2
- heat-functional-convg-mysql-lbaasv2-non-apache
- heat-functional-convg-mysql-lbaasv2-py35

View File

@ -290,7 +290,7 @@ for the ``heat_template_version`` key:
or or
2017-09-01 | pike 2017-09-01 | pike
------------------- -----------------
The key with value ``2017-09-01`` or ``pike`` indicates that the YAML The key with value ``2017-09-01`` or ``pike`` indicates that the YAML
document is a HOT template and it may contain features added and/or removed document is a HOT template and it may contain features added and/or removed
up until the Pike release. This version adds the ``make_url`` function for up until the Pike release. This version adds the ``make_url`` function for
@ -1599,7 +1599,7 @@ rather than later when processing a template.
str_replace_vstrict str_replace_vstrict
------------------ -------------------
``str_replace_vstrict`` behaves identically to the ``str_replace_vstrict`` behaves identically to the
``str_replace_strict`` function, only an error is raised if any of the ``str_replace_strict`` function, only an error is raised if any of the
params are empty. This may help catch issues (i.e., prevent params are empty. This may help catch issues (i.e., prevent

View File

@ -13,7 +13,6 @@
import os import os
from cinderclient import client as cinder_client from cinderclient import client as cinder_client
from gnocchiclient import client as gnocchi_client
from heat.common.i18n import _ from heat.common.i18n import _
from heatclient import client as heat_client from heatclient import client as heat_client
from keystoneauth1 import exceptions as kc_exceptions from keystoneauth1 import exceptions as kc_exceptions
@ -65,7 +64,6 @@ class ClientManager(object):
CINDERCLIENT_VERSION = '2' CINDERCLIENT_VERSION = '2'
HEATCLIENT_VERSION = '1' HEATCLIENT_VERSION = '1'
NOVA_API_VERSION = '2.1' NOVA_API_VERSION = '2.1'
GNOCCHI_VERSION = '1'
def __init__(self, conf, admin_credentials=False): def __init__(self, conf, admin_credentials=False):
self.conf = conf self.conf = conf
@ -87,7 +85,6 @@ 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.metric_client = self._get_metric_client()
def _username(self): def _username(self):
if self.admin_credentials: if self.admin_credentials:
@ -186,14 +183,3 @@ class ClientManager(object):
'service_type': 'object-store'}, 'service_type': 'object-store'},
} }
return swift_client.Connection(**args) return swift_client.Connection(**args)
def _get_metric_client(self):
adapter_options = {'interface': 'public',
'region_name': self.conf.region}
args = {
'session': self.identity_client.session,
'adapter_options': adapter_options
}
return gnocchi_client.Client(version=self.GNOCCHI_VERSION,
**args)

View File

@ -156,9 +156,6 @@ HeatGroup = [
help='Count of retries to edit config file during sighup. If ' help='Count of retries to edit config file during sighup. If '
'another worker already edit config file, file can be ' 'another worker already edit config file, file can be '
'busy, so need to wait and try edit file again.'), 'busy, so need to wait and try edit file again.'),
cfg.StrOpt('heat_config_notify_script',
default=('heat-config-notify'),
help="Path to the script heat-config-notify"),
] ]

View File

@ -110,7 +110,6 @@ 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.metric_client = self.manager.metric_client
self.client = self.orchestration_client self.client = self.orchestration_client

View File

@ -1,79 +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 uuid
from zaqarclient.queues.v2 import client as zaqarclient
from heat_integrationtests.common import test
from heat_integrationtests.functional import functional_base
class ZaqarEventSinkTest(functional_base.FunctionalTestsBase):
template = '''
heat_template_version: "2013-05-23"
resources:
test_resource:
type: OS::Heat::TestResource
properties:
value: ok
'''
def test_events(self):
queue_id = str(uuid.uuid4())
environment = {'event_sinks': [{'type': 'zaqar-queue',
'target': queue_id,
'ttl': 120}]}
stack_identifier = self.stack_create(
template=self.template,
environment=environment)
stack_name, stack_id = stack_identifier.split('/')
conf = {
'auth_opts': {
'backend': 'keystone',
'options': {
'os_username': self.conf.username,
'os_password': self.conf.password,
'os_project_name': self.conf.project_name,
'os_auth_url': self.conf.auth_url,
'os_user_domain_id': self.conf.user_domain_id,
'os_project_domain_id': self.conf.project_domain_id,
'os_user_domain_name': self.conf.user_domain_name,
'os_project_domain_name': self.conf.project_domain_name
}
}
}
zaqar = zaqarclient.Client(conf=conf)
queue = zaqar.queue(queue_id)
def validate_messages():
messages = list(queue.messages())
if len(messages) < 4:
return False
types = [m.body['type'] for m in messages]
self.assertEqual(['os.heat.event'] * 4, types)
resources = set([m.body['payload'][
'resource_name'] for m in messages])
self.assertEqual(set([stack_name, 'test_resource']), resources)
stack_ids = [m.body['payload']['stack_id'] for m in messages]
self.assertEqual([stack_id] * 4, stack_ids)
statuses = [m.body['payload']['resource_status'] for m in messages]
statuses.sort()
self.assertEqual(['COMPLETE', 'COMPLETE',
'IN_PROGRESS', 'IN_PROGRESS'], statuses)
actions = [m.body['payload']['resource_action'] for m in messages]
self.assertEqual(['CREATE'] * 4, actions)
return True
self.assertTrue(test.call_until_true(20, 0, validate_messages))

View File

@ -1,155 +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 heat_integrationtests.functional import functional_base
class LoadBalancerv2Test(functional_base.FunctionalTestsBase):
create_template = '''
heat_template_version: 2016-04-08
parameters:
subnet:
type: string
resources:
loadbalancer:
type: OS::Neutron::LBaaS::LoadBalancer
properties:
description: aLoadBalancer
vip_subnet: { get_param: subnet }
listener:
type: OS::Neutron::LBaaS::Listener
properties:
description: aListener
loadbalancer: { get_resource: loadbalancer }
protocol: HTTP
protocol_port: 80
connection_limit: 5555
pool:
type: OS::Neutron::LBaaS::Pool
properties:
description: aPool
lb_algorithm: ROUND_ROBIN
protocol: HTTP
listener: { get_resource: listener }
poolmember:
type: OS::Neutron::LBaaS::PoolMember
properties:
address: 1.1.1.1
pool: { get_resource: pool }
protocol_port: 1111
subnet: { get_param: subnet }
weight: 255
# pm2
healthmonitor:
type: OS::Neutron::LBaaS::HealthMonitor
properties:
delay: 3
type: HTTP
timeout: 3
max_retries: 3
pool: { get_resource: pool }
outputs:
loadbalancer:
value: { get_attr: [ loadbalancer, show ] }
pool:
value: { get_attr: [ pool, show ] }
poolmember:
value: { get_attr: [ poolmember, show ] }
listener:
value: { get_attr: [ listener, show ] }
healthmonitor:
value: { get_attr: [ healthmonitor, show ] }
'''
add_member = '''
poolmember2:
type: OS::Neutron::LBaaS::PoolMember
properties:
address: 2.2.2.2
pool: { get_resource: pool }
protocol_port: 2222
subnet: { get_param: subnet }
weight: 222
'''
def setUp(self):
super(LoadBalancerv2Test, self).setUp()
if not self.is_network_extension_supported('lbaasv2'):
self.skipTest('LBaasv2 extension not available, skipping')
def test_create_update_loadbalancer(self):
parameters = {
'subnet': self.conf.fixed_subnet_name,
}
stack_identifier = self.stack_create(template=self.create_template,
parameters=parameters)
stack = self.client.stacks.get(stack_identifier)
output = self._stack_output(stack, 'loadbalancer')
self.assertEqual('ONLINE', output['operating_status'])
template = self.create_template.replace('ROUND_ROBIN', 'SOURCE_IP')
template = template.replace('3', '6')
template = template.replace('255', '256')
template = template.replace('5555', '7777')
template = template.replace('aLoadBalancer', 'updatedLoadBalancer')
template = template.replace('aPool', 'updatedPool')
template = template.replace('aListener', 'updatedListener')
self.update_stack(stack_identifier, template=template,
parameters=parameters)
stack = self.client.stacks.get(stack_identifier)
output = self._stack_output(stack, 'loadbalancer')
self.assertEqual('ONLINE', output['operating_status'])
self.assertEqual('updatedLoadBalancer', output['description'])
output = self._stack_output(stack, 'pool')
self.assertEqual('SOURCE_IP', output['lb_algorithm'])
self.assertEqual('updatedPool', output['description'])
output = self._stack_output(stack, 'poolmember')
self.assertEqual(256, output['weight'])
output = self._stack_output(stack, 'healthmonitor')
self.assertEqual(6, output['delay'])
self.assertEqual(6, output['timeout'])
self.assertEqual(6, output['max_retries'])
output = self._stack_output(stack, 'listener')
self.assertEqual(7777, output['connection_limit'])
self.assertEqual('updatedListener', output['description'])
def test_add_delete_poolmember(self):
parameters = {
'subnet': self.conf.fixed_subnet_name,
}
stack_identifier = self.stack_create(template=self.create_template,
parameters=parameters)
stack = self.client.stacks.get(stack_identifier)
output = self._stack_output(stack, 'loadbalancer')
self.assertEqual('ONLINE', output['operating_status'])
output = self._stack_output(stack, 'pool')
self.assertEqual(1, len(output['members']))
# add pool member
template = self.create_template.replace('# pm2', self.add_member)
self.update_stack(stack_identifier, template=template,
parameters=parameters)
stack = self.client.stacks.get(stack_identifier)
output = self._stack_output(stack, 'loadbalancer')
self.assertEqual('ONLINE', output['operating_status'])
output = self._stack_output(stack, 'pool')
self.assertEqual(2, len(output['members']))
# delete pool member
self.update_stack(stack_identifier, template=self.create_template,
parameters=parameters)
stack = self.client.stacks.get(stack_identifier)
output = self._stack_output(stack, 'loadbalancer')
self.assertEqual('ONLINE', output['operating_status'])
output = self._stack_output(stack, 'pool')
self.assertEqual(1, len(output['members']))

View File

@ -1,126 +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 json
import os
import subprocess
import sys
import tempfile
import time
from oslo_utils import timeutils
from heat_integrationtests.common import exceptions
from heat_integrationtests.functional import functional_base
class ZaqarSignalTransportTest(functional_base.FunctionalTestsBase):
server_template = '''
heat_template_version: "2013-05-23"
parameters:
flavor:
type: string
image:
type: string
network:
type: string
resources:
server:
type: OS::Nova::Server
properties:
image: {get_param: image}
flavor: {get_param: flavor}
user_data_format: SOFTWARE_CONFIG
software_config_transport: ZAQAR_MESSAGE
networks: [{network: {get_param: network}}]
config:
type: OS::Heat::SoftwareConfig
properties:
config: echo 'foo'
deployment:
type: OS::Heat::SoftwareDeployment
properties:
config: {get_resource: config}
server: {get_resource: server}
signal_transport: ZAQAR_SIGNAL
outputs:
data:
value: {get_attr: [deployment, deploy_stdout]}
'''
conf_template = '''
[zaqar]
user_id = %(user_id)s
password = %(password)s
project_id = %(project_id)s
auth_url = %(auth_url)s
queue_id = %(queue_id)s
'''
def test_signal_queues(self):
parms = {'flavor': self.conf.minimal_instance_type,
'network': self.conf.fixed_network_name,
'image': self.conf.minimal_image_ref}
stack_identifier = self.stack_create(
parameters=parms,
template=self.server_template,
expected_status=None)
metadata = self.wait_for_deploy_metadata_set(stack_identifier)
config = metadata['os-collect-config']['zaqar']
conf_content = self.conf_template % config
fd, temp_path = tempfile.mkstemp()
os.write(fd, conf_content.encode('utf-8'))
os.close(fd)
cmd = ['os-collect-config', '--one-time',
'--config-file=%s' % temp_path, 'zaqar']
proc = subprocess.Popen(cmd, stdout=subprocess.PIPE)
stdout_value = proc.communicate()[0]
data = json.loads(stdout_value.decode('utf-8'))
self.assertEqual(config, data['zaqar']['os-collect-config']['zaqar'])
proc = subprocess.Popen(cmd, stdout=subprocess.PIPE)
stdout_value = proc.communicate()[0]
data = json.loads(stdout_value.decode('utf-8'))
fd, temp_path = tempfile.mkstemp()
os.write(fd,
json.dumps(data['zaqar']['deployments'][0]).encode('utf-8'))
os.close(fd)
cmd = [sys.executable, self.conf.heat_config_notify_script, temp_path]
proc = subprocess.Popen(cmd,
stderr=subprocess.PIPE,
stdin=subprocess.PIPE)
proc.communicate(
json.dumps({'deploy_stdout': 'here!'}).encode('utf-8'))
self._wait_for_stack_status(stack_identifier, 'CREATE_COMPLETE')
stack = self.client.stacks.get(stack_identifier)
self.assertEqual('here!', stack.outputs[0]['output_value'])
def wait_for_deploy_metadata_set(self, stack):
build_timeout = self.conf.build_timeout
build_interval = self.conf.build_interval
start = timeutils.utcnow()
while timeutils.delta_seconds(start,
timeutils.utcnow()) < build_timeout:
server_metadata = self.client.resources.metadata(
stack, 'server')
if server_metadata.get('deployments'):
return server_metadata
time.sleep(build_interval)
message = ('Deployment resources failed to be created within '
'the required time (%s s).' %
(build_timeout))
raise exceptions.TimeoutException(message)

View File

@ -1,72 +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 json
from keystoneclient.v3 import client as keystoneclient
from zaqarclient.queues.v2 import client as zaqarclient
from heat_integrationtests.functional import functional_base
class ZaqarWaitConditionTest(functional_base.FunctionalTestsBase):
template = '''
heat_template_version: "2013-05-23"
resources:
wait_condition:
type: OS::Heat::WaitCondition
properties:
handle: {get_resource: wait_handle}
timeout: 120
wait_handle:
type: OS::Heat::WaitConditionHandle
properties:
signal_transport: ZAQAR_SIGNAL
outputs:
wait_data:
value: {'Fn::Select': ['data_id', {get_attr: [wait_condition, data]}]}
'''
def test_signal_queues(self):
stack_identifier = self.stack_create(
template=self.template,
expected_status=None)
self._wait_for_resource_status(stack_identifier, 'wait_handle',
'CREATE_COMPLETE')
resource = self.client.resources.get(stack_identifier, 'wait_handle')
signal = json.loads(resource.attributes['signal'])
ks = keystoneclient.Client(
auth_url=signal['auth_url'],
user_id=signal['user_id'],
password=signal['password'],
project_id=signal['project_id'])
endpoint = ks.service_catalog.url_for(
service_type='messaging', endpoint_type='publicURL')
conf = {
'auth_opts': {
'backend': 'keystone',
'options': {
'os_auth_token': ks.auth_token,
'os_project_id': signal['project_id']
}
}
}
zaqar = zaqarclient.Client(endpoint, conf=conf)
queue = zaqar.queue(signal['queue_id'])
queue.post({'body': {'data': 'here!', 'id': 'data_id'}, 'ttl': 600})
self._wait_for_stack_status(stack_identifier, 'CREATE_COMPLETE')
stack = self.client.stacks.get(stack_identifier)
self.assertEqual('here!', stack.outputs[0]['output_value'])

View File

@ -50,7 +50,6 @@ function _config_iniset {
iniset $conf_file heat_plugin image_ref Fedora-Cloud-Base-26-1.5.x86_64 iniset $conf_file heat_plugin image_ref Fedora-Cloud-Base-26-1.5.x86_64
iniset $conf_file heat_plugin boot_config_env $DEST/heat-templates/hot/software-config/boot-config/test_image_env.yaml iniset $conf_file heat_plugin boot_config_env $DEST/heat-templates/hot/software-config/boot-config/test_image_env.yaml
iniset $conf_file heat_plugin heat_config_notify_script $DEST/heat-templates/hot/software-config/elements/heat-config/bin/heat-config-notify
iniset $conf_file heat_plugin minimal_image_ref cirros-0.3.5-x86_64-disk iniset $conf_file heat_plugin minimal_image_ref cirros-0.3.5-x86_64-disk
# Skip ReloadOnSighupTest. Most jobs now run with apache+uwsgi, so the test has no significance # Skip ReloadOnSighupTest. Most jobs now run with apache+uwsgi, so the test has no significance
@ -65,7 +64,6 @@ function _config_iniset {
if [ "$DISABLE_CONVERGENCE" == "true" ]; then if [ "$DISABLE_CONVERGENCE" == "true" ]; then
iniset $conf_file heat_plugin convergence_engine_enabled false iniset $conf_file heat_plugin convergence_engine_enabled false
fi fi
cat $conf_file
} }
@ -73,6 +71,7 @@ function _config_functionaltests
{ {
local conf_file=$DEST/heat/heat_integrationtests/heat_integrationtests.conf local conf_file=$DEST/heat/heat_integrationtests/heat_integrationtests.conf
_config_iniset $conf_file _config_iniset $conf_file
cat $conf_file
} }
function _config_tempest_plugin function _config_tempest_plugin
@ -80,6 +79,8 @@ function _config_tempest_plugin
local conf_file=$DEST/tempest/etc/tempest.conf local conf_file=$DEST/tempest/etc/tempest.conf
iniset_multiline $conf_file service_available heat_plugin True iniset_multiline $conf_file service_available heat_plugin True
_config_iniset $conf_file _config_iniset $conf_file
iniset $conf_file heat_plugin heat_config_notify_script $DEST/heat-templates/hot/software-config/elements/heat-config/bin/heat-config-notify
cat $conf_file
} }
_config_functionaltests _config_functionaltests

View File

@ -1,69 +0,0 @@
heat_template_version: 2015-10-15
description: |
App server that is a member of Neutron Pool.
parameters:
image:
type: string
flavor:
type: string
net:
type: string
sec_group:
type: string
pool:
type: string
app_port:
type: number
timeout:
type: number
subnet:
type: string
resources:
config:
type: OS::Test::WebAppConfig
properties:
app_port: { get_param: app_port }
wc_curl_cli: { get_attr: [ handle, curl_cli ] }
server:
type: OS::Nova::Server
properties:
image: { get_param: image }
flavor: { get_param: flavor }
networks:
- network: { get_param: net }
security_groups:
- { get_param: sec_group }
user_data_format: RAW
user_data: { get_resource: config }
handle:
type: OS::Heat::WaitConditionHandle
waiter:
type: OS::Heat::WaitCondition
depends_on: server
properties:
timeout: { get_param: timeout }
handle: { get_resource: handle }
pool_member:
type: OS::Neutron::LBaaS::PoolMember
depends_on: waiter
properties:
address: { get_attr: [ server, networks, { get_param: net }, 0 ] }
pool: { get_param: pool }
protocol_port: { get_param: app_port }
subnet: { get_param: subnet }

View File

@ -1,37 +0,0 @@
heat_template_version: 2013-05-23
parameters:
metric_id:
type: string
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::Aodh::GnocchiAggregationByMetricsAlarm
properties:
metrics:
- {get_param: metric_id}
comparison_operator: ge
evaluation_periods: 1
granularity: 60
aggregation_method: mean
threshold: 10
alarm_actions:
- str_replace:
template: trust+url
params:
url: {get_attr: [scaleup_policy, signal_url]}
outputs:
asg_size:
value: {get_attr: [asg, current_size]}

View File

@ -1,116 +0,0 @@
heat_template_version: 2015-04-30
description: |
Template which tests Neutron load balancing requests to members of
Heat AutoScalingGroup. This uses LBaas V2.
Instances must be running some webserver on a given app_port
producing HTTP response that is different between servers
but stable over time for given server.
parameters:
flavor:
type: string
image:
type: string
net:
type: string
subnet:
type: string
public_net:
type: string
app_port:
type: number
default: 8080
lb_port:
type: number
default: 80
timeout:
type: number
default: 600
resources:
sec_group:
type: OS::Neutron::SecurityGroup
properties:
rules:
- remote_ip_prefix: 0.0.0.0/0
protocol: tcp
port_range_min: { get_param: app_port }
port_range_max: { get_param: app_port }
asg:
type: OS::Heat::AutoScalingGroup
properties:
desired_capacity: 1
max_size: 2
min_size: 1
resource:
type: OS::Test::NeutronAppServer
properties:
image: { get_param: image }
flavor: { get_param: flavor }
net: { get_param: net}
sec_group: { get_resource: sec_group }
app_port: { get_param: app_port }
pool: { get_resource: pool }
subnet: { get_param: subnet }
timeout: { get_param: timeout }
scale_up:
type: OS::Heat::ScalingPolicy
properties:
adjustment_type: change_in_capacity
auto_scaling_group_id: { get_resource: asg }
scaling_adjustment: 1
scale_down:
type: OS::Heat::ScalingPolicy
properties:
adjustment_type: change_in_capacity
auto_scaling_group_id: { get_resource: asg }
scaling_adjustment: -1
health_monitor:
type: OS::Neutron::LBaaS::HealthMonitor
properties:
delay: 3
type: HTTP
timeout: 3
max_retries: 3
pool: { get_resource: pool }
pool:
type: OS::Neutron::LBaaS::Pool
properties:
lb_algorithm: ROUND_ROBIN
protocol: HTTP
listener: { get_resource: listener }
listener:
type: OS::Neutron::LBaaS::Listener
properties:
loadbalancer: { get_resource: loadbalancer }
protocol: HTTP
protocol_port: { get_param: lb_port }
loadbalancer:
type: OS::Neutron::LBaaS::LoadBalancer
properties:
vip_subnet: { get_param: subnet }
floating_ip:
type: OS::Neutron::FloatingIP
properties:
floating_network: { get_param: public_net }
port_id: { get_attr: [loadbalancer, vip_port_id] }
outputs:
lburl:
description: URL of the loadbalanced app
value:
str_replace:
template: http://IP_ADDRESS:PORT
params:
IP_ADDRESS: { get_attr: [ floating_ip, floating_ip_address ] }
PORT: { get_param: lb_port }

View File

@ -1,64 +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 datetime
from heat.common import timeutils
from oslo_log import log as logging
from heat_integrationtests.common import test
from heat_integrationtests.scenario import scenario_base
LOG = logging.getLogger(__name__)
class AodhAlarmTest(scenario_base.ScenarioTestsBase):
"""Class is responsible for testing of aodh usage."""
def setUp(self):
super(AodhAlarmTest, self).setUp()
self.template = self._load_template(__file__,
'test_aodh_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.warning('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."""
# create metric
metric = self.metric_client.metric.create({
'name': 'my_metric',
'archive_policy_name': 'high',
})
# create the stack
parameters = {'metric_id': metric['id']}
stack_identifier = self.stack_create(template=self.template,
parameters=parameters)
measures = [{'timestamp': timeutils.isotime(datetime.datetime.now()),
'value': 100}, {'timestamp': timeutils.isotime(
datetime.datetime.now() + datetime.timedelta(
minutes=1)), 'value': 100}]
# send measures(should cause the alarm to fire)
self.metric_client.metric.add_measures(metric['id'], measures)
# 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))
# cleanup metric
self.metric_client.metric.delete(metric['id'])

View File

@ -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.
import time
import requests
from heat_integrationtests.common import test
from heat_integrationtests.scenario import scenario_base
class AutoscalingLoadBalancerv2Test(scenario_base.ScenarioTestsBase):
"""The class is responsible for testing ASG + LBv2 scenario.
The very common use case tested is an autoscaling group
of some web application servers behind a loadbalancer.
"""
def setUp(self):
super(AutoscalingLoadBalancerv2Test, self).setUp()
self.template_name = 'test_autoscaling_lbv2_neutron.yaml'
self.app_server_template_name = 'app_server_lbv2_neutron.yaml'
self.webapp_template_name = 'netcat-webapp.yaml'
if not self.is_network_extension_supported('lbaasv2'):
self.skipTest('LBaasv2 extension not available, skipping')
def check_num_responses(self, url, expected_num, retries=20):
resp = set()
for count in range(retries):
time.sleep(2)
try:
r = requests.get(url, verify=self.verify_cert)
except requests.exceptions.ConnectionError:
# The LB may not be up yet, let's retry
continue
# skip unsuccessful requests
if r.status_code == 200:
resp.add(r.text)
if len(resp) == expected_num:
break
self.assertEqual(expected_num, len(resp))
def test_autoscaling_loadbalancer_neutron(self):
"""Check work of AutoScaing and Neutron LBaaS v2 resource in Heat.
The scenario is the following:
1. Launch a stack with a load balancer and autoscaling group
of one server, wait until stack create is complete.
2. Check that there is only one distinctive response from
loadbalanced IP.
3. Signal the scale_up policy, wait until all resources in
autoscaling group are complete.
4. Check that now there are two distinctive responses from
loadbalanced IP.
"""
parameters = {
'flavor': self.conf.minimal_instance_type,
'image': self.conf.minimal_image_ref,
'net': self.conf.fixed_network_name,
'subnet': self.conf.fixed_subnet_name,
'public_net': self.conf.floating_network_name
}
app_server_template = self._load_template(
__file__, self.app_server_template_name, self.sub_dir
)
webapp_template = self._load_template(
__file__, self.webapp_template_name, self.sub_dir
)
files = {'appserver.yaml': app_server_template,
'webapp.yaml': webapp_template}
env = {'resource_registry':
{'OS::Test::NeutronAppServer': 'appserver.yaml',
'OS::Test::WebAppConfig': 'webapp.yaml'}}
# Launch stack
sid = self.launch_stack(
template_name=self.template_name,
parameters=parameters,
files=files,
environment=env
)
stack = self.client.stacks.get(sid)
lb_url = self._stack_output(stack, 'lburl')
# Check number of distinctive responces, must be 1
self.check_num_responses(lb_url, 1)
# Signal the scaling hook
self.client.resources.signal(sid, 'scale_up')
# Wait for AutoScalingGroup update to finish
asg = self.client.resources.get(sid, 'asg')
test.call_until_true(self.conf.build_timeout,
self.conf.build_interval,
self.check_autoscale_complete,
asg.physical_resource_id, 2, sid, 'scale_up')
# Check number of distinctive responses, must now be 2
self.check_num_responses(lb_url, 2)

View File

@ -35,7 +35,6 @@ python-ceilometerclient>=2.5.0 # Apache-2.0
python-cinderclient>=3.3.0 # Apache-2.0 python-cinderclient>=3.3.0 # Apache-2.0
python-designateclient>=2.7.0 # Apache-2.0 python-designateclient>=2.7.0 # Apache-2.0
python-glanceclient>=2.8.0 # Apache-2.0 python-glanceclient>=2.8.0 # Apache-2.0
gnocchiclient>=3.3.1 # Apache-2.0
python-heatclient>=1.10.0 # Apache-2.0 python-heatclient>=1.10.0 # Apache-2.0
python-keystoneclient>=3.8.0 # Apache-2.0 python-keystoneclient>=3.8.0 # Apache-2.0
python-magnumclient>=2.1.0 # Apache-2.0 python-magnumclient>=2.1.0 # Apache-2.0

View File

@ -24,6 +24,5 @@ testtools>=2.2.0 # MIT
testresources>=2.0.0 # Apache-2.0/BSD testresources>=2.0.0 # Apache-2.0/BSD
reno>=2.5.0 # Apache-2.0 reno>=2.5.0 # Apache-2.0
# Next are used in integration tests only # Next are used in integration tests only
os-collect-config>=5.0.0 # Apache-2.0
paramiko>=2.0.0 # LGPLv2.1+ paramiko>=2.0.0 # LGPLv2.1+
tempest>=17.1.0 # Apache-2.0 tempest>=17.1.0 # Apache-2.0