Attila Fazekas | 7cf2a22 | 2013-08-02 13:49:10 +0200 | [diff] [blame] | 1 | # Licensed under the Apache License, Version 2.0 (the "License"); |
| 2 | # you may not use this file except in compliance with the License. |
| 3 | # You may obtain 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, |
| 9 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 10 | # See the License for the specific language governing permissions and |
| 11 | # limitations under the License. |
| 12 | |
| 13 | import socket |
| 14 | import subprocess |
| 15 | |
Masayuki Igawa | 259c113 | 2013-10-31 17:48:44 +0900 | [diff] [blame] | 16 | from tempest.common.utils import data_utils |
Matthew Treinish | 88f49ef | 2014-01-29 18:36:27 +0000 | [diff] [blame] | 17 | from tempest import config |
Attila Fazekas | 7cf2a22 | 2013-08-02 13:49:10 +0200 | [diff] [blame] | 18 | import tempest.stress.stressaction as stressaction |
| 19 | import tempest.test |
| 20 | |
Matthew Treinish | 88f49ef | 2014-01-29 18:36:27 +0000 | [diff] [blame] | 21 | CONF = config.CONF |
| 22 | |
Attila Fazekas | 7cf2a22 | 2013-08-02 13:49:10 +0200 | [diff] [blame] | 23 | |
| 24 | class FloatingStress(stressaction.StressAction): |
| 25 | |
| 26 | # from the scenario manager |
| 27 | def ping_ip_address(self, ip_address): |
| 28 | cmd = ['ping', '-c1', '-w1', ip_address] |
| 29 | |
| 30 | proc = subprocess.Popen(cmd, |
| 31 | stdout=subprocess.PIPE, |
| 32 | stderr=subprocess.PIPE) |
| 33 | proc.wait() |
| 34 | success = proc.returncode == 0 |
| 35 | self.logger.info("%s(%s): %s", self.server_id, self.floating['ip'], |
| 36 | "pong!" if success else "no pong :(") |
| 37 | return success |
| 38 | |
| 39 | def tcp_connect_scan(self, addr, port): |
| 40 | # like tcp |
| 41 | s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) |
| 42 | try: |
| 43 | s.connect((addr, port)) |
| 44 | except socket.error as exc: |
| 45 | self.logger.info("%s(%s): %s", self.server_id, self.floating['ip'], |
| 46 | str(exc)) |
| 47 | return False |
| 48 | self.logger.info("%s(%s): Connected :)", self.server_id, |
| 49 | self.floating['ip']) |
| 50 | s.close() |
| 51 | return True |
| 52 | |
| 53 | def check_port_ssh(self): |
| 54 | def func(): |
| 55 | return self.tcp_connect_scan(self.floating['ip'], 22) |
| 56 | if not tempest.test.call_until_true(func, self.check_timeout, |
| 57 | self.check_interval): |
| 58 | raise RuntimeError("Cannot connect to the ssh port.") |
| 59 | |
| 60 | def check_icmp_echo(self): |
| 61 | def func(): |
| 62 | return self.ping_ip_address(self.floating['ip']) |
| 63 | if not tempest.test.call_until_true(func, self.check_timeout, |
| 64 | self.check_interval): |
| 65 | raise RuntimeError("Cannot ping the machine.") |
| 66 | |
| 67 | def _create_vm(self): |
Masayuki Igawa | 259c113 | 2013-10-31 17:48:44 +0900 | [diff] [blame] | 68 | self.name = name = data_utils.rand_name("instance") |
Attila Fazekas | 7cf2a22 | 2013-08-02 13:49:10 +0200 | [diff] [blame] | 69 | servers_client = self.manager.servers_client |
| 70 | self.logger.info("creating %s" % name) |
| 71 | vm_args = self.vm_extra_args.copy() |
Attila Fazekas | 6c7244a | 2014-02-26 15:11:48 +0100 | [diff] [blame] | 72 | vm_args['security_groups'] = [self.sec_grp] |
Attila Fazekas | 7cf2a22 | 2013-08-02 13:49:10 +0200 | [diff] [blame] | 73 | resp, server = servers_client.create_server(name, self.image, |
| 74 | self.flavor, |
| 75 | **vm_args) |
| 76 | self.server_id = server['id'] |
| 77 | assert(resp.status == 202) |
| 78 | if self.wait_after_vm_create: |
| 79 | self.manager.servers_client.wait_for_server_status(self.server_id, |
| 80 | 'ACTIVE') |
| 81 | |
| 82 | def _destroy_vm(self): |
| 83 | self.logger.info("deleting %s" % self.server_id) |
| 84 | resp, _ = self.manager.servers_client.delete_server(self.server_id) |
| 85 | assert(resp.status == 204) # It cannot be 204 if I had to wait.. |
| 86 | self.manager.servers_client.wait_for_server_termination(self.server_id) |
| 87 | self.logger.info("deleted %s" % self.server_id) |
| 88 | |
| 89 | def _create_sec_group(self): |
| 90 | sec_grp_cli = self.manager.security_groups_client |
Masayuki Igawa | 259c113 | 2013-10-31 17:48:44 +0900 | [diff] [blame] | 91 | s_name = data_utils.rand_name('sec_grp-') |
| 92 | s_description = data_utils.rand_name('desc-') |
Attila Fazekas | 6c7244a | 2014-02-26 15:11:48 +0100 | [diff] [blame] | 93 | _, self.sec_grp = sec_grp_cli.create_security_group(s_name, |
| 94 | s_description) |
Attila Fazekas | 7cf2a22 | 2013-08-02 13:49:10 +0200 | [diff] [blame] | 95 | create_rule = sec_grp_cli.create_security_group_rule |
Attila Fazekas | 6c7244a | 2014-02-26 15:11:48 +0100 | [diff] [blame] | 96 | create_rule(self.sec_grp['id'], 'tcp', 22, 22) |
| 97 | create_rule(self.sec_grp['id'], 'icmp', -1, -1) |
Attila Fazekas | 7cf2a22 | 2013-08-02 13:49:10 +0200 | [diff] [blame] | 98 | |
| 99 | def _destroy_sec_grp(self): |
| 100 | sec_grp_cli = self.manager.security_groups_client |
Attila Fazekas | 6c7244a | 2014-02-26 15:11:48 +0100 | [diff] [blame] | 101 | sec_grp_cli.delete_security_group(self.sec_grp['id']) |
Attila Fazekas | 7cf2a22 | 2013-08-02 13:49:10 +0200 | [diff] [blame] | 102 | |
| 103 | def _create_floating_ip(self): |
| 104 | floating_cli = self.manager.floating_ips_client |
| 105 | _, self.floating = floating_cli.create_floating_ip(self.floating_pool) |
| 106 | |
| 107 | def _destroy_floating_ip(self): |
| 108 | cli = self.manager.floating_ips_client |
| 109 | cli.delete_floating_ip(self.floating['id']) |
| 110 | cli.wait_for_resource_deletion(self.floating['id']) |
| 111 | self.logger.info("Deleted Floating IP %s", str(self.floating['ip'])) |
| 112 | |
| 113 | def setUp(self, **kwargs): |
Matthew Treinish | 88f49ef | 2014-01-29 18:36:27 +0000 | [diff] [blame] | 114 | self.image = CONF.compute.image_ref |
| 115 | self.flavor = CONF.compute.flavor_ref |
Attila Fazekas | 7cf2a22 | 2013-08-02 13:49:10 +0200 | [diff] [blame] | 116 | self.vm_extra_args = kwargs.get('vm_extra_args', {}) |
| 117 | self.wait_after_vm_create = kwargs.get('wait_after_vm_create', |
| 118 | True) |
| 119 | self.new_vm = kwargs.get('new_vm', False) |
| 120 | self.new_sec_grp = kwargs.get('new_sec_group', False) |
| 121 | self.new_floating = kwargs.get('new_floating', False) |
| 122 | self.reboot = kwargs.get('reboot', False) |
| 123 | self.floating_pool = kwargs.get('floating_pool', None) |
| 124 | self.verify = kwargs.get('verify', ('check_port_ssh', |
| 125 | 'check_icmp_echo')) |
| 126 | self.check_timeout = kwargs.get('check_timeout', 120) |
| 127 | self.check_interval = kwargs.get('check_interval', 1) |
| 128 | self.wait_for_disassociate = kwargs.get('wait_for_disassociate', |
| 129 | True) |
| 130 | |
| 131 | # allocate floating |
| 132 | if not self.new_floating: |
| 133 | self._create_floating_ip() |
| 134 | # add security group |
| 135 | if not self.new_sec_grp: |
| 136 | self._create_sec_group() |
| 137 | # create vm |
| 138 | if not self.new_vm: |
| 139 | self._create_vm() |
| 140 | |
| 141 | def wait_disassociate(self): |
| 142 | cli = self.manager.floating_ips_client |
| 143 | |
| 144 | def func(): |
| 145 | _, floating = cli.get_floating_ip_details(self.floating['id']) |
| 146 | return floating['instance_id'] is None |
| 147 | |
| 148 | if not tempest.test.call_until_true(func, self.check_timeout, |
| 149 | self.check_interval): |
| 150 | raise RuntimeError("IP disassociate timeout!") |
| 151 | |
| 152 | def run_core(self): |
| 153 | cli = self.manager.floating_ips_client |
| 154 | cli.associate_floating_ip_to_server(self.floating['ip'], |
| 155 | self.server_id) |
| 156 | for method in self.verify: |
| 157 | m = getattr(self, method) |
| 158 | m() |
| 159 | cli.disassociate_floating_ip_from_server(self.floating['ip'], |
| 160 | self.server_id) |
| 161 | if self.wait_for_disassociate: |
| 162 | self.wait_disassociate() |
| 163 | |
| 164 | def run(self): |
| 165 | if self.new_sec_grp: |
| 166 | self._create_sec_group() |
| 167 | if self.new_floating: |
| 168 | self._create_floating_ip() |
| 169 | if self.new_vm: |
| 170 | self._create_vm() |
| 171 | if self.reboot: |
| 172 | self.manager.servers_client.reboot(self.server_id, 'HARD') |
| 173 | |
| 174 | self.run_core() |
| 175 | |
| 176 | if self.new_vm: |
| 177 | self._destroy_vm() |
| 178 | if self.new_floating: |
| 179 | self._destroy_floating_ip() |
| 180 | if self.new_sec_grp: |
| 181 | self._destroy_sec_grp() |
| 182 | |
| 183 | def tearDown(self): |
| 184 | if not self.new_vm: |
| 185 | self._destroy_vm() |
| 186 | if not self.new_floating: |
| 187 | self._destroy_floating_ip() |
| 188 | if not self.new_sec_grp: |
| 189 | self._destroy_sec_grp() |