| # |
| # 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 AutoscalingLoadBalancerTest(scenario_base.ScenarioTestsBase): |
| """ |
| The class is responsible for testing ASG + LB scenario. |
| |
| The very common use case tested is an autoscaling group |
| of some web application servers behind a loadbalancer. |
| """ |
| |
| def setUp(self): |
| super(AutoscalingLoadBalancerTest, self).setUp() |
| self.template_name = 'test_autoscaling_lb_neutron.yaml' |
| self.app_server_template_name = 'app_server_neutron.yaml' |
| self.webapp_template_name = 'netcat-webapp.yaml' |
| |
| def check_num_responses(self, url, expected_num, retries=10): |
| resp = set() |
| for count in range(retries): |
| time.sleep(1) |
| r = requests.get(url) |
| # skip unsuccessfull requests |
| if r.status_code == 200: |
| resp.add(r.text) |
| self.assertEqual(expected_num, len(resp)) |
| |
| def autoscale_complete(self, stack_id, expected_num): |
| res_list = self.client.resources.list(stack_id) |
| all_res_complete = all(res.resource_status in ('UPDATE_COMPLETE', |
| 'CREATE_COMPLETE') |
| for res in res_list) |
| all_res = len(res_list) == expected_num |
| return all_res and all_res_complete |
| |
| def test_autoscaling_loadbalancer_neutron(self): |
| """ |
| Check work of AutoScaing and Neutron LBaaS 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_port': 8080, |
| 'lb_port': 80, |
| 'timeout': 600 |
| } |
| |
| 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.autoscale_complete, |
| asg.physical_resource_id, 2) |
| |
| # Check number of distinctive responses, must now be 2 |
| self.check_num_responses(lb_url, 2) |