| Steve Baker | 647b345 | 2014-07-30 11:04:42 +1200 | [diff] [blame] | 1 | #    Licensed under the Apache License, Version 2.0 (the "License"); you may | 
|  | 2 | #    not use this file except in compliance with the License. You may obtain | 
|  | 3 | #    a copy of the License at | 
|  | 4 | # | 
|  | 5 | #         http://www.apache.org/licenses/LICENSE-2.0 | 
|  | 6 | # | 
|  | 7 | #    Unless required by applicable law or agreed to in writing, software | 
|  | 8 | #    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT | 
|  | 9 | #    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the | 
|  | 10 | #    License for the specific language governing permissions and limitations | 
|  | 11 | #    under the License. | 
|  | 12 |  | 
|  | 13 | import json | 
| Steve Baker | 647b345 | 2014-07-30 11:04:42 +1200 | [diff] [blame] | 14 |  | 
|  | 15 | from heat_integrationtests.common import exceptions | 
| Anastasia Kuznetsova | e45bfff | 2015-02-25 12:50:34 +0400 | [diff] [blame] | 16 | from heat_integrationtests.scenario import scenario_base | 
| Steve Baker | 647b345 | 2014-07-30 11:04:42 +1200 | [diff] [blame] | 17 |  | 
| Steve Baker | 647b345 | 2014-07-30 11:04:42 +1200 | [diff] [blame] | 18 |  | 
| Anastasia Kuznetsova | e45bfff | 2015-02-25 12:50:34 +0400 | [diff] [blame] | 19 | class CfnInitIntegrationTest(scenario_base.ScenarioTestsBase): | 
|  | 20 | """ | 
|  | 21 | The class is responsible for testing cfn-init and cfn-signal workability | 
|  | 22 | """ | 
| Steve Baker | 647b345 | 2014-07-30 11:04:42 +1200 | [diff] [blame] | 23 |  | 
|  | 24 | def setUp(self): | 
|  | 25 | super(CfnInitIntegrationTest, self).setUp() | 
| Steve Baker | 647b345 | 2014-07-30 11:04:42 +1200 | [diff] [blame] | 26 |  | 
| Sergey Kraynev | ef9d842 | 2015-02-13 03:41:46 -0500 | [diff] [blame] | 27 | def check_stack(self, sid): | 
| Anastasia Kuznetsova | e45bfff | 2015-02-25 12:50:34 +0400 | [diff] [blame] | 28 | # Check status of all resources | 
|  | 29 | for res in ('WaitHandle', 'SmokeSecurityGroup', 'SmokeKeys', | 
| Rakesh H S | eecee65 | 2015-07-15 17:44:41 +0530 | [diff] [blame] | 30 | 'CfnUser', 'SmokeServer', 'SmokeServerElasticIp'): | 
| Anastasia Kuznetsova | e45bfff | 2015-02-25 12:50:34 +0400 | [diff] [blame] | 31 | self._wait_for_resource_status( | 
|  | 32 | sid, res, 'CREATE_COMPLETE') | 
| Steve Baker | 647b345 | 2014-07-30 11:04:42 +1200 | [diff] [blame] | 33 |  | 
|  | 34 | server_resource = self.client.resources.get(sid, 'SmokeServer') | 
|  | 35 | server_id = server_resource.physical_resource_id | 
|  | 36 | server = self.compute_client.servers.get(server_id) | 
| Steve Baker | 647b345 | 2014-07-30 11:04:42 +1200 | [diff] [blame] | 37 |  | 
|  | 38 | try: | 
|  | 39 | self._wait_for_resource_status( | 
|  | 40 | sid, 'WaitCondition', 'CREATE_COMPLETE') | 
|  | 41 | except (exceptions.StackResourceBuildErrorException, | 
|  | 42 | exceptions.TimeoutException) as e: | 
|  | 43 | raise e | 
|  | 44 | finally: | 
|  | 45 | # attempt to log the server console regardless of WaitCondition | 
|  | 46 | # going to complete. This allows successful and failed cloud-init | 
|  | 47 | # logs to be compared | 
|  | 48 | self._log_console_output(servers=[server]) | 
|  | 49 |  | 
| Steve Baker | 647b345 | 2014-07-30 11:04:42 +1200 | [diff] [blame] | 50 | stack = self.client.stacks.get(sid) | 
|  | 51 |  | 
|  | 52 | # This is an assert of great significance, as it means the following | 
|  | 53 | # has happened: | 
|  | 54 | # - cfn-init read the provided metadata and wrote out a file | 
|  | 55 | # - a user was created and credentials written to the server | 
|  | 56 | # - a cfn-signal was built which was signed with provided credentials | 
|  | 57 | # - the wait condition was fulfilled and the stack has changed state | 
|  | 58 | wait_status = json.loads( | 
|  | 59 | self._stack_output(stack, 'WaitConditionStatus')) | 
|  | 60 | self.assertEqual('smoke test complete', wait_status['smoke_status']) | 
|  | 61 |  | 
| Rakesh H S | eecee65 | 2015-07-15 17:44:41 +0530 | [diff] [blame] | 62 | # Check EIP attributes. | 
|  | 63 | server_floatingip_id = self._stack_output(stack, | 
|  | 64 | 'ElasticIp_Id') | 
|  | 65 | self.assertIsNotNone(server_floatingip_id) | 
|  | 66 |  | 
|  | 67 | # Fetch EIP details. | 
|  | 68 | net_show = self.network_client.show_floatingip( | 
|  | 69 | floatingip=server_floatingip_id) | 
|  | 70 | floating_ip = net_show['floatingip']['floating_ip_address'] | 
|  | 71 | port_id = net_show['floatingip']['port_id'] | 
|  | 72 |  | 
|  | 73 | # Ensure that EIP was assigned to server. | 
|  | 74 | port_show = self.network_client.show_port(port=port_id) | 
|  | 75 | self.assertEqual(server.id, port_show['port']['device_id']) | 
|  | 76 | server_ip = self._stack_output(stack, 'SmokeServerElasticIp') | 
|  | 77 | self.assertEqual(server_ip, floating_ip) | 
| Steve Baker | d6de8a2 | 2015-03-12 14:42:51 +1300 | [diff] [blame] | 78 |  | 
|  | 79 | # Check that created server is reachable | 
|  | 80 | if not self._ping_ip_address(server_ip): | 
|  | 81 | self._log_console_output(servers=[server]) | 
|  | 82 | self.fail( | 
|  | 83 | "Timed out waiting for %s to become reachable" % server_ip) | 
|  | 84 |  | 
| Anastasia Kuznetsova | e45bfff | 2015-02-25 12:50:34 +0400 | [diff] [blame] | 85 | # Check that the user can authenticate with the generated keypair | 
| Steve Baker | 647b345 | 2014-07-30 11:04:42 +1200 | [diff] [blame] | 86 | if self.keypair: | 
| Steve Baker | 647b345 | 2014-07-30 11:04:42 +1200 | [diff] [blame] | 87 | try: | 
|  | 88 | linux_client = self.get_remote_client( | 
|  | 89 | server_ip, username='ec2-user') | 
|  | 90 | linux_client.validate_authentication() | 
|  | 91 | except (exceptions.ServerUnreachable, | 
|  | 92 | exceptions.SSHTimeout) as e: | 
|  | 93 | self._log_console_output(servers=[server]) | 
|  | 94 | raise e | 
|  | 95 |  | 
|  | 96 | def test_server_cfn_init(self): | 
| Anastasia Kuznetsova | e45bfff | 2015-02-25 12:50:34 +0400 | [diff] [blame] | 97 | """ | 
|  | 98 | Check cfn-init and cfn-signal availability on the created server. | 
|  | 99 |  | 
|  | 100 | The alternative scenario is the following: | 
|  | 101 | 1. Create a stack with a server and configured security group. | 
|  | 102 | 2. Check that all stack resources were created. | 
|  | 103 | 3. Check that created server is reachable. | 
|  | 104 | 4. Check that stack was created successfully. | 
|  | 105 | 5. Check that is it possible to connect to server | 
|  | 106 | via generated keypair. | 
|  | 107 | """ | 
|  | 108 | parameters = { | 
| Sergey Kraynev | 83ef84d | 2015-04-29 05:31:54 -0400 | [diff] [blame] | 109 | 'key_name': self.keypair_name, | 
|  | 110 | 'flavor': self.conf.instance_type, | 
|  | 111 | 'image': self.conf.image_ref, | 
|  | 112 | 'timeout': self.conf.build_timeout, | 
| Rabi Mishra | ec4b03b | 2015-05-23 02:20:47 +0530 | [diff] [blame] | 113 | 'subnet': self.net['subnets'][0], | 
| Anastasia Kuznetsova | e45bfff | 2015-02-25 12:50:34 +0400 | [diff] [blame] | 114 | } | 
|  | 115 |  | 
|  | 116 | # Launch stack | 
|  | 117 | stack_id = self.launch_stack( | 
|  | 118 | template_name="test_server_cfn_init.yaml", | 
| Steve Baker | d6de8a2 | 2015-03-12 14:42:51 +1300 | [diff] [blame] | 119 | parameters=parameters, | 
|  | 120 | expected_status=None | 
| Anastasia Kuznetsova | e45bfff | 2015-02-25 12:50:34 +0400 | [diff] [blame] | 121 | ) | 
|  | 122 |  | 
|  | 123 | # Check stack | 
|  | 124 | self.check_stack(stack_id) |