Soren Hansen | bc1d3a0 | 2011-09-08 13:33:17 +0200 | [diff] [blame] | 1 | |
| 2 | import json |
| 3 | import time |
| 4 | |
| 5 | from kong import exceptions |
| 6 | from kong import openstack |
Soren Hansen | 6adacc8 | 2011-09-09 13:34:35 +0200 | [diff] [blame] | 7 | from kong import tests |
Soren Hansen | bc1d3a0 | 2011-09-08 13:33:17 +0200 | [diff] [blame] | 8 | from kong.common import ssh |
| 9 | |
| 10 | import unittest2 as unittest |
| 11 | |
| 12 | |
Soren Hansen | 6adacc8 | 2011-09-09 13:34:35 +0200 | [diff] [blame] | 13 | class ServerActionsTest(tests.FunctionalTest): |
Soren Hansen | bc1d3a0 | 2011-09-08 13:33:17 +0200 | [diff] [blame] | 14 | |
Soren Hansen | bc1d3a0 | 2011-09-08 13:33:17 +0200 | [diff] [blame] | 15 | def setUp(self): |
Soren Hansen | 6adacc8 | 2011-09-09 13:34:35 +0200 | [diff] [blame] | 16 | super(ServerActionsTest, self).setUp() |
Soren Hansen | d6b047a | 2011-09-09 13:39:32 +0200 | [diff] [blame] | 17 | self.os = openstack.Manager(self.nova) |
Soren Hansen | bc1d3a0 | 2011-09-08 13:33:17 +0200 | [diff] [blame] | 18 | |
Brian Waldon | 883cb26 | 2011-11-02 11:30:07 -0400 | [diff] [blame] | 19 | self.multi_node = self.nova['multi_node'] == 'yes' |
Soren Hansen | a86180a | 2011-09-09 16:22:26 +0200 | [diff] [blame] | 20 | self.image_ref = self.glance['image_id'] |
Brian Waldon | 883cb26 | 2011-11-02 11:30:07 -0400 | [diff] [blame] | 21 | self.image_ref_alt = self.glance['image_id_alt'] |
Soren Hansen | a86180a | 2011-09-09 16:22:26 +0200 | [diff] [blame] | 22 | self.flavor_ref = self.nova['flavor_ref'] |
| 23 | self.flavor_ref_alt = self.nova['flavor_ref_alt'] |
Brian Waldon | 883cb26 | 2011-11-02 11:30:07 -0400 | [diff] [blame] | 24 | self.ssh_timeout = int(self.nova['ssh_timeout']) |
| 25 | self.build_timeout = int(self.nova['build_timeout']) |
Soren Hansen | bc1d3a0 | 2011-09-08 13:33:17 +0200 | [diff] [blame] | 26 | |
| 27 | self.server_password = 'testpwd' |
Soren Hansen | 5f4ad83 | 2011-09-09 14:08:19 +0200 | [diff] [blame] | 28 | self.server_name = 'stacktester1' |
Soren Hansen | bc1d3a0 | 2011-09-08 13:33:17 +0200 | [diff] [blame] | 29 | |
| 30 | expected_server = { |
Soren Hansen | 5f4ad83 | 2011-09-09 14:08:19 +0200 | [diff] [blame] | 31 | 'name': self.server_name, |
| 32 | 'imageRef': self.image_ref, |
| 33 | 'flavorRef': self.flavor_ref, |
| 34 | 'adminPass': self.server_password, |
Soren Hansen | bc1d3a0 | 2011-09-08 13:33:17 +0200 | [diff] [blame] | 35 | } |
| 36 | |
| 37 | created_server = self.os.nova.create_server(expected_server) |
| 38 | |
| 39 | self.server_id = created_server['id'] |
Soren Hansen | 5f4ad83 | 2011-09-09 14:08:19 +0200 | [diff] [blame] | 40 | self._wait_for_server_status(self.server_id, 'ACTIVE') |
Soren Hansen | bc1d3a0 | 2011-09-08 13:33:17 +0200 | [diff] [blame] | 41 | |
| 42 | server = self.os.nova.get_server(self.server_id) |
Soren Hansen | bc1d3a0 | 2011-09-08 13:33:17 +0200 | [diff] [blame] | 43 | self.access_ip = server['addresses']['public'][0]['addr'] |
| 44 | |
| 45 | # Ensure server came up |
Brian Waldon | 883cb26 | 2011-11-02 11:30:07 -0400 | [diff] [blame] | 46 | if self.ssh_timeout: |
| 47 | self._assert_ssh_password() |
Soren Hansen | bc1d3a0 | 2011-09-08 13:33:17 +0200 | [diff] [blame] | 48 | |
| 49 | def tearDown(self): |
| 50 | self.os.nova.delete_server(self.server_id) |
| 51 | |
| 52 | def _get_ssh_client(self, password): |
| 53 | return ssh.Client(self.access_ip, 'root', password, self.ssh_timeout) |
| 54 | |
| 55 | def _assert_ssh_password(self, password=None): |
| 56 | _password = password or self.server_password |
| 57 | client = self._get_ssh_client(_password) |
| 58 | self.assertTrue(client.test_connection_auth()) |
| 59 | |
Soren Hansen | 5f4ad83 | 2011-09-09 14:08:19 +0200 | [diff] [blame] | 60 | def _wait_for_server_status(self, server_id, status): |
Soren Hansen | bc1d3a0 | 2011-09-08 13:33:17 +0200 | [diff] [blame] | 61 | try: |
Soren Hansen | 5f4ad83 | 2011-09-09 14:08:19 +0200 | [diff] [blame] | 62 | self.os.nova.wait_for_server_status(server_id, status, |
| 63 | timeout=self.build_timeout) |
Soren Hansen | bc1d3a0 | 2011-09-08 13:33:17 +0200 | [diff] [blame] | 64 | except exceptions.TimeoutException: |
| 65 | self.fail("Server failed to change status to %s" % status) |
| 66 | |
| 67 | def _get_boot_time(self): |
| 68 | """Return the time the server was started""" |
| 69 | output = self._read_file("/proc/uptime") |
| 70 | uptime = float(output.split().pop(0)) |
| 71 | return time.time() - uptime |
| 72 | |
Soren Hansen | 5f4ad83 | 2011-09-09 14:08:19 +0200 | [diff] [blame] | 73 | def _write_file(self, filename, contents, password=None): |
| 74 | command = "echo -n %s > %s" % (contents, filename) |
| 75 | return self._exec_command(command, password) |
Soren Hansen | bc1d3a0 | 2011-09-08 13:33:17 +0200 | [diff] [blame] | 76 | |
Soren Hansen | 5f4ad83 | 2011-09-09 14:08:19 +0200 | [diff] [blame] | 77 | def _read_file(self, filename, password=None): |
| 78 | command = "cat %s" % filename |
| 79 | return self._exec_command(command, password) |
Soren Hansen | bc1d3a0 | 2011-09-08 13:33:17 +0200 | [diff] [blame] | 80 | |
Soren Hansen | 5f4ad83 | 2011-09-09 14:08:19 +0200 | [diff] [blame] | 81 | def _exec_command(self, command, password=None): |
| 82 | if password is None: |
| 83 | password = self.server_password |
| 84 | client = self._get_ssh_client(password) |
Soren Hansen | bc1d3a0 | 2011-09-08 13:33:17 +0200 | [diff] [blame] | 85 | return client.exec_command(command) |
| 86 | |
Brian Waldon | 883cb26 | 2011-11-02 11:30:07 -0400 | [diff] [blame] | 87 | def test_reboot_server(self): |
| 88 | """Reboot a server SOFT and HARD""" |
Soren Hansen | bc1d3a0 | 2011-09-08 13:33:17 +0200 | [diff] [blame] | 89 | # SSH and get the uptime |
Brian Waldon | 883cb26 | 2011-11-02 11:30:07 -0400 | [diff] [blame] | 90 | if self.ssh_timeout: |
| 91 | initial_time_started = self._get_boot_time() |
| 92 | else: |
| 93 | intitial_time_started = 0 |
Soren Hansen | bc1d3a0 | 2011-09-08 13:33:17 +0200 | [diff] [blame] | 94 | |
| 95 | # Make reboot request |
Soren Hansen | 5f4ad83 | 2011-09-09 14:08:19 +0200 | [diff] [blame] | 96 | post_body = json.dumps({'reboot': {'type': 'SOFT'}}) |
Soren Hansen | bc1d3a0 | 2011-09-08 13:33:17 +0200 | [diff] [blame] | 97 | url = "/servers/%s/action" % self.server_id |
| 98 | response, body = self.os.nova.request('POST', url, body=post_body) |
| 99 | self.assertEqual(response['status'], '202') |
| 100 | |
| 101 | # Assert status transition |
Brian Waldon | 883cb26 | 2011-11-02 11:30:07 -0400 | [diff] [blame] | 102 | self._wait_for_server_status(self.server_id, 'REBOOT') |
Soren Hansen | 5f4ad83 | 2011-09-09 14:08:19 +0200 | [diff] [blame] | 103 | self._wait_for_server_status(self.server_id, 'ACTIVE') |
Soren Hansen | bc1d3a0 | 2011-09-08 13:33:17 +0200 | [diff] [blame] | 104 | |
| 105 | # SSH and verify uptime is less than before |
Brian Waldon | 883cb26 | 2011-11-02 11:30:07 -0400 | [diff] [blame] | 106 | if self.ssh_timeout: |
| 107 | post_reboot_time_started = self._get_boot_time() |
| 108 | self.assertTrue(initial_time_started < post_reboot_time_started) |
Soren Hansen | bc1d3a0 | 2011-09-08 13:33:17 +0200 | [diff] [blame] | 109 | |
Brian Waldon | 883cb26 | 2011-11-02 11:30:07 -0400 | [diff] [blame] | 110 | # SSH and get the uptime for the next reboot |
| 111 | initial_time_started = post_reboot_time_started |
Soren Hansen | bc1d3a0 | 2011-09-08 13:33:17 +0200 | [diff] [blame] | 112 | |
| 113 | # Make reboot request |
Soren Hansen | 5f4ad83 | 2011-09-09 14:08:19 +0200 | [diff] [blame] | 114 | post_body = json.dumps({'reboot': {'type': 'HARD'}}) |
Soren Hansen | bc1d3a0 | 2011-09-08 13:33:17 +0200 | [diff] [blame] | 115 | url = "/servers/%s/action" % self.server_id |
| 116 | response, body = self.os.nova.request('POST', url, body=post_body) |
| 117 | self.assertEqual(response['status'], '202') |
| 118 | |
| 119 | # Assert status transition |
Brian Waldon | 883cb26 | 2011-11-02 11:30:07 -0400 | [diff] [blame] | 120 | # KNOWN-ISSUE 884906 |
Soren Hansen | 5f4ad83 | 2011-09-09 14:08:19 +0200 | [diff] [blame] | 121 | #self._wait_for_server_status(self.server_id, 'HARD_REBOOT') |
Brian Waldon | 883cb26 | 2011-11-02 11:30:07 -0400 | [diff] [blame] | 122 | self._wait_for_server_status(self.server_id, 'REBOOT') |
Soren Hansen | 5f4ad83 | 2011-09-09 14:08:19 +0200 | [diff] [blame] | 123 | self._wait_for_server_status(self.server_id, 'ACTIVE') |
Soren Hansen | bc1d3a0 | 2011-09-08 13:33:17 +0200 | [diff] [blame] | 124 | |
| 125 | # SSH and verify uptime is less than before |
Brian Waldon | 883cb26 | 2011-11-02 11:30:07 -0400 | [diff] [blame] | 126 | if self.ssh_timeout: |
| 127 | post_reboot_time_started = self._get_boot_time() |
| 128 | self.assertTrue(initial_time_started < post_reboot_time_started) |
| 129 | test_reboot_server.tags = ['nova'] |
Soren Hansen | bc1d3a0 | 2011-09-08 13:33:17 +0200 | [diff] [blame] | 130 | |
Brian Waldon | 883cb26 | 2011-11-02 11:30:07 -0400 | [diff] [blame] | 131 | def test_change_password(self): |
Soren Hansen | bc1d3a0 | 2011-09-08 13:33:17 +0200 | [diff] [blame] | 132 | """Change root password of a server""" |
Soren Hansen | bc1d3a0 | 2011-09-08 13:33:17 +0200 | [diff] [blame] | 133 | # Change server password |
Soren Hansen | 5f4ad83 | 2011-09-09 14:08:19 +0200 | [diff] [blame] | 134 | post_body = json.dumps({'changePassword': {'adminPass': 'test123'}}) |
Soren Hansen | bc1d3a0 | 2011-09-08 13:33:17 +0200 | [diff] [blame] | 135 | url = '/servers/%s/action' % self.server_id |
| 136 | response, body = self.os.nova.request('POST', url, body=post_body) |
| 137 | |
| 138 | # Assert status transition |
| 139 | self.assertEqual('202', response['status']) |
Soren Hansen | 5f4ad83 | 2011-09-09 14:08:19 +0200 | [diff] [blame] | 140 | self._wait_for_server_status(self.server_id, 'PASSWORD') |
| 141 | self._wait_for_server_status(self.server_id, 'ACTIVE') |
Soren Hansen | bc1d3a0 | 2011-09-08 13:33:17 +0200 | [diff] [blame] | 142 | |
| 143 | # SSH into server using new password |
Brian Waldon | 883cb26 | 2011-11-02 11:30:07 -0400 | [diff] [blame] | 144 | if self.ssh_timeout: |
| 145 | self._assert_ssh_password('test123') |
| 146 | test_change_password.tags = ['nova'] |
Soren Hansen | bc1d3a0 | 2011-09-08 13:33:17 +0200 | [diff] [blame] | 147 | |
Soren Hansen | 5f4ad83 | 2011-09-09 14:08:19 +0200 | [diff] [blame] | 148 | def test_rebuild(self): |
Soren Hansen | bc1d3a0 | 2011-09-08 13:33:17 +0200 | [diff] [blame] | 149 | """Rebuild a server""" |
| 150 | |
Soren Hansen | 5f4ad83 | 2011-09-09 14:08:19 +0200 | [diff] [blame] | 151 | FILENAME = '/tmp/testfile' |
| 152 | CONTENTS = 'WORDS' |
| 153 | |
| 154 | # write file to server |
Brian Waldon | 883cb26 | 2011-11-02 11:30:07 -0400 | [diff] [blame] | 155 | if self.ssh_timeout: |
| 156 | self._write_file(FILENAME, CONTENTS) |
| 157 | self.assertEqual(self._read_file(FILENAME), CONTENTS) |
Soren Hansen | bc1d3a0 | 2011-09-08 13:33:17 +0200 | [diff] [blame] | 158 | |
| 159 | # Make rebuild request |
Soren Hansen | 5f4ad83 | 2011-09-09 14:08:19 +0200 | [diff] [blame] | 160 | post_body = json.dumps({'rebuild': {'imageRef': self.image_ref_alt}}) |
Soren Hansen | bc1d3a0 | 2011-09-08 13:33:17 +0200 | [diff] [blame] | 161 | url = '/servers/%s/action' % self.server_id |
| 162 | response, body = self.os.nova.request('POST', url, body=post_body) |
| 163 | |
Soren Hansen | 5f4ad83 | 2011-09-09 14:08:19 +0200 | [diff] [blame] | 164 | # check output |
Soren Hansen | bc1d3a0 | 2011-09-08 13:33:17 +0200 | [diff] [blame] | 165 | self.assertEqual('202', response['status']) |
Soren Hansen | 5f4ad83 | 2011-09-09 14:08:19 +0200 | [diff] [blame] | 166 | rebuilt_server = json.loads(body)['server'] |
| 167 | generated_password = rebuilt_server['adminPass'] |
| 168 | |
| 169 | # Ensure correct status transition |
Brian Waldon | 883cb26 | 2011-11-02 11:30:07 -0400 | [diff] [blame] | 170 | self._wait_for_server_status(self.server_id, 'REBUILD') |
Soren Hansen | 5f4ad83 | 2011-09-09 14:08:19 +0200 | [diff] [blame] | 171 | self._wait_for_server_status(self.server_id, 'ACTIVE') |
Soren Hansen | bc1d3a0 | 2011-09-08 13:33:17 +0200 | [diff] [blame] | 172 | |
| 173 | # Treats an issue where we ssh'd in too soon after rebuild |
Brian Waldon | 883cb26 | 2011-11-02 11:30:07 -0400 | [diff] [blame] | 174 | #TODO(bcwaldon): fix the Xen driver so we don't have to sleep here |
Soren Hansen | bc1d3a0 | 2011-09-08 13:33:17 +0200 | [diff] [blame] | 175 | time.sleep(30) |
| 176 | |
| 177 | # Check that the instance's imageRef matches the new imageRef |
| 178 | server = self.os.nova.get_server(self.server_id) |
| 179 | ref_match = self.image_ref_alt == server['image']['links'][0]['href'] |
| 180 | id_match = self.image_ref_alt == server['image']['id'] |
| 181 | self.assertTrue(ref_match or id_match) |
| 182 | |
| 183 | # SSH into the server to ensure it came back up |
Brian Waldon | 883cb26 | 2011-11-02 11:30:07 -0400 | [diff] [blame] | 184 | if self.ssh_timeout: |
| 185 | self._assert_ssh_password(generated_password) |
Soren Hansen | bc1d3a0 | 2011-09-08 13:33:17 +0200 | [diff] [blame] | 186 | |
Brian Waldon | 883cb26 | 2011-11-02 11:30:07 -0400 | [diff] [blame] | 187 | # make sure file is gone |
| 188 | self.assertEqual(self._read_file(FILENAME, generated_password), '') |
Soren Hansen | 5f4ad83 | 2011-09-09 14:08:19 +0200 | [diff] [blame] | 189 | |
Brian Waldon | 883cb26 | 2011-11-02 11:30:07 -0400 | [diff] [blame] | 190 | # test again with a specified password |
| 191 | self._write_file(FILENAME, CONTENTS, generated_password) |
| 192 | _contents = self._read_file(FILENAME, generated_password) |
| 193 | self.assertEqual(_contents, CONTENTS) |
Soren Hansen | 5f4ad83 | 2011-09-09 14:08:19 +0200 | [diff] [blame] | 194 | |
| 195 | specified_password = 'some_password' |
| 196 | |
| 197 | # Make rebuild request |
| 198 | post_body = json.dumps({ |
| 199 | 'rebuild': { |
| 200 | 'imageRef': self.image_ref, |
| 201 | 'adminPass': specified_password, |
| 202 | } |
| 203 | }) |
| 204 | url = '/servers/%s/action' % self.server_id |
| 205 | response, body = self.os.nova.request('POST', url, body=post_body) |
| 206 | |
| 207 | # check output |
| 208 | self.assertEqual('202', response['status']) |
| 209 | rebuilt_server = json.loads(body)['server'] |
| 210 | self.assertEqual(rebuilt_server['adminPass'], specified_password) |
| 211 | |
| 212 | # Ensure correct status transition |
Brian Waldon | 883cb26 | 2011-11-02 11:30:07 -0400 | [diff] [blame] | 213 | self._wait_for_server_status(self.server_id, 'REBUILD') |
Soren Hansen | 5f4ad83 | 2011-09-09 14:08:19 +0200 | [diff] [blame] | 214 | self._wait_for_server_status(self.server_id, 'ACTIVE') |
| 215 | |
| 216 | # Treats an issue where we ssh'd in too soon after rebuild |
| 217 | time.sleep(30) |
| 218 | |
| 219 | # Check that the instance's imageRef matches the new imageRef |
| 220 | server = self.os.nova.get_server(self.server_id) |
| 221 | ref_match = self.image_ref == server['image']['links'][0]['href'] |
| 222 | id_match = self.image_ref == server['image']['id'] |
| 223 | self.assertTrue(ref_match or id_match) |
| 224 | |
Soren Hansen | 5f4ad83 | 2011-09-09 14:08:19 +0200 | [diff] [blame] | 225 | # make sure file is gone |
Brian Waldon | 883cb26 | 2011-11-02 11:30:07 -0400 | [diff] [blame] | 226 | if self.ssh_timeout: |
| 227 | self.assertEqual(self._read_file(FILENAME, specified_password), '') |
Soren Hansen | fce58c5 | 2011-09-09 16:07:13 +0200 | [diff] [blame] | 228 | test_rebuild.tags = ['nova'] |
Soren Hansen | bc1d3a0 | 2011-09-08 13:33:17 +0200 | [diff] [blame] | 229 | |
Brian Waldon | 883cb26 | 2011-11-02 11:30:07 -0400 | [diff] [blame] | 230 | def test_resize(self): |
Soren Hansen | bc1d3a0 | 2011-09-08 13:33:17 +0200 | [diff] [blame] | 231 | """Resize a server""" |
Brian Waldon | 883cb26 | 2011-11-02 11:30:07 -0400 | [diff] [blame] | 232 | |
Soren Hansen | bc1d3a0 | 2011-09-08 13:33:17 +0200 | [diff] [blame] | 233 | # Make resize request |
Soren Hansen | 5f4ad83 | 2011-09-09 14:08:19 +0200 | [diff] [blame] | 234 | post_body = json.dumps({'resize': {'flavorRef': self.flavor_ref_alt}}) |
Soren Hansen | bc1d3a0 | 2011-09-08 13:33:17 +0200 | [diff] [blame] | 235 | url = '/servers/%s/action' % self.server_id |
| 236 | response, body = self.os.nova.request('POST', url, body=post_body) |
| 237 | |
| 238 | # Wait for status transition |
| 239 | self.assertEqual('202', response['status']) |
Brian Waldon | 883cb26 | 2011-11-02 11:30:07 -0400 | [diff] [blame] | 240 | self._wait_for_server_status(self.server_id, 'VERIFY_RESIZE') |
Soren Hansen | bc1d3a0 | 2011-09-08 13:33:17 +0200 | [diff] [blame] | 241 | |
| 242 | # Ensure API reports new flavor |
| 243 | server = self.os.nova.get_server(self.server_id) |
| 244 | self.assertEqual(self.flavor_ref_alt, server['flavor']['id']) |
| 245 | |
| 246 | #SSH into the server to ensure it came back up |
Brian Waldon | 883cb26 | 2011-11-02 11:30:07 -0400 | [diff] [blame] | 247 | if self.ssh_timeout: |
| 248 | self._assert_ssh_password() |
Soren Hansen | bc1d3a0 | 2011-09-08 13:33:17 +0200 | [diff] [blame] | 249 | |
| 250 | # Make confirmResize request |
Soren Hansen | 5f4ad83 | 2011-09-09 14:08:19 +0200 | [diff] [blame] | 251 | post_body = json.dumps({'confirmResize': 'null'}) |
Soren Hansen | bc1d3a0 | 2011-09-08 13:33:17 +0200 | [diff] [blame] | 252 | url = '/servers/%s/action' % self.server_id |
| 253 | response, body = self.os.nova.request('POST', url, body=post_body) |
| 254 | |
| 255 | # Wait for status transition |
| 256 | self.assertEqual('204', response['status']) |
Soren Hansen | 5f4ad83 | 2011-09-09 14:08:19 +0200 | [diff] [blame] | 257 | self._wait_for_server_status(self.server_id, 'ACTIVE') |
Soren Hansen | bc1d3a0 | 2011-09-08 13:33:17 +0200 | [diff] [blame] | 258 | |
| 259 | # Ensure API still reports new flavor |
| 260 | server = self.os.nova.get_server(self.server_id) |
| 261 | self.assertEqual(self.flavor_ref_alt, server['flavor']['id']) |
Brian Waldon | 883cb26 | 2011-11-02 11:30:07 -0400 | [diff] [blame] | 262 | test_resize.tags = ['nova'] |
Soren Hansen | bc1d3a0 | 2011-09-08 13:33:17 +0200 | [diff] [blame] | 263 | |
Brian Waldon | 883cb26 | 2011-11-02 11:30:07 -0400 | [diff] [blame] | 264 | def test_resize_revert(self): |
Soren Hansen | bc1d3a0 | 2011-09-08 13:33:17 +0200 | [diff] [blame] | 265 | """Resize a server, then revert""" |
Soren Hansen | bc1d3a0 | 2011-09-08 13:33:17 +0200 | [diff] [blame] | 266 | # Make resize request |
Soren Hansen | 5f4ad83 | 2011-09-09 14:08:19 +0200 | [diff] [blame] | 267 | post_body = json.dumps({'resize': {'flavorRef': self.flavor_ref_alt}}) |
Soren Hansen | bc1d3a0 | 2011-09-08 13:33:17 +0200 | [diff] [blame] | 268 | url = '/servers/%s/action' % self.server_id |
| 269 | response, body = self.os.nova.request('POST', url, body=post_body) |
| 270 | |
| 271 | # Wait for status transition |
| 272 | self.assertEqual('202', response['status']) |
Brian Waldon | 883cb26 | 2011-11-02 11:30:07 -0400 | [diff] [blame] | 273 | self._wait_for_server_status(self.server_id, 'VERIFY_RESIZE') |
Soren Hansen | bc1d3a0 | 2011-09-08 13:33:17 +0200 | [diff] [blame] | 274 | |
| 275 | # SSH into the server to ensure it came back up |
Brian Waldon | 883cb26 | 2011-11-02 11:30:07 -0400 | [diff] [blame] | 276 | if self.ssh_timeout: |
| 277 | self._assert_ssh_password() |
Soren Hansen | bc1d3a0 | 2011-09-08 13:33:17 +0200 | [diff] [blame] | 278 | |
| 279 | # Ensure API reports new flavor |
| 280 | server = self.os.nova.get_server(self.server_id) |
| 281 | self.assertEqual(self.flavor_ref_alt, server['flavor']['id']) |
| 282 | |
| 283 | # Make revertResize request |
Soren Hansen | 5f4ad83 | 2011-09-09 14:08:19 +0200 | [diff] [blame] | 284 | post_body = json.dumps({'revertResize': 'null'}) |
Soren Hansen | bc1d3a0 | 2011-09-08 13:33:17 +0200 | [diff] [blame] | 285 | url = '/servers/%s/action' % self.server_id |
| 286 | response, body = self.os.nova.request('POST', url, body=post_body) |
| 287 | |
| 288 | # Assert status transition |
| 289 | self.assertEqual('202', response['status']) |
Soren Hansen | 5f4ad83 | 2011-09-09 14:08:19 +0200 | [diff] [blame] | 290 | self._wait_for_server_status(self.server_id, 'ACTIVE') |
Soren Hansen | bc1d3a0 | 2011-09-08 13:33:17 +0200 | [diff] [blame] | 291 | |
| 292 | # Ensure flavor ref was reverted to original |
| 293 | server = self.os.nova.get_server(self.server_id) |
| 294 | self.assertEqual(self.flavor_ref, server['flavor']['id']) |
Brian Waldon | 883cb26 | 2011-11-02 11:30:07 -0400 | [diff] [blame] | 295 | test_resize_revert.tags = ['nova'] |
Soren Hansen | bc1d3a0 | 2011-09-08 13:33:17 +0200 | [diff] [blame] | 296 | |
| 297 | |
Brian Waldon | 883cb26 | 2011-11-02 11:30:07 -0400 | [diff] [blame] | 298 | class SnapshotTests(tests.FunctionalTest): |
Soren Hansen | bc1d3a0 | 2011-09-08 13:33:17 +0200 | [diff] [blame] | 299 | |
| 300 | def setUp(self): |
Brian Waldon | 883cb26 | 2011-11-02 11:30:07 -0400 | [diff] [blame] | 301 | super(SnapshotTests, self).setUp() |
| 302 | self.os = openstack.Manager(self.nova) |
Soren Hansen | bc1d3a0 | 2011-09-08 13:33:17 +0200 | [diff] [blame] | 303 | |
Brian Waldon | 883cb26 | 2011-11-02 11:30:07 -0400 | [diff] [blame] | 304 | self.image_ref = self.glance['image_id'] |
| 305 | self.flavor_ref = self.nova['flavor_ref'] |
| 306 | self.ssh_timeout = int(self.nova['ssh_timeout']) |
| 307 | self.build_timeout = int(self.nova['build_timeout']) |
Soren Hansen | bc1d3a0 | 2011-09-08 13:33:17 +0200 | [diff] [blame] | 308 | |
Soren Hansen | 5f4ad83 | 2011-09-09 14:08:19 +0200 | [diff] [blame] | 309 | self.server_name = 'stacktester1' |
Soren Hansen | bc1d3a0 | 2011-09-08 13:33:17 +0200 | [diff] [blame] | 310 | |
| 311 | expected_server = { |
Soren Hansen | 5f4ad83 | 2011-09-09 14:08:19 +0200 | [diff] [blame] | 312 | 'name': self.server_name, |
| 313 | 'imageRef': self.image_ref, |
| 314 | 'flavorRef': self.flavor_ref, |
Soren Hansen | bc1d3a0 | 2011-09-08 13:33:17 +0200 | [diff] [blame] | 315 | } |
| 316 | |
| 317 | created_server = self.os.nova.create_server(expected_server) |
| 318 | self.server_id = created_server['id'] |
| 319 | |
| 320 | def tearDown(self): |
| 321 | self.os.nova.delete_server(self.server_id) |
| 322 | |
Soren Hansen | 5f4ad83 | 2011-09-09 14:08:19 +0200 | [diff] [blame] | 323 | def _wait_for_server_status(self, server_id, status): |
Soren Hansen | bc1d3a0 | 2011-09-08 13:33:17 +0200 | [diff] [blame] | 324 | try: |
Soren Hansen | 5f4ad83 | 2011-09-09 14:08:19 +0200 | [diff] [blame] | 325 | self.os.nova.wait_for_server_status(server_id, status, |
| 326 | timeout=self.build_timeout) |
Soren Hansen | bc1d3a0 | 2011-09-08 13:33:17 +0200 | [diff] [blame] | 327 | except exceptions.TimeoutException: |
| 328 | self.fail("Server failed to change status to %s" % status) |
| 329 | |
Brian Waldon | 883cb26 | 2011-11-02 11:30:07 -0400 | [diff] [blame] | 330 | def test_snapshot(self): |
Soren Hansen | bc1d3a0 | 2011-09-08 13:33:17 +0200 | [diff] [blame] | 331 | """Create image from an existing server""" |
| 332 | |
| 333 | # Wait for server to come up before running this test |
Soren Hansen | 5f4ad83 | 2011-09-09 14:08:19 +0200 | [diff] [blame] | 334 | self._wait_for_server_status(self.server_id, 'ACTIVE') |
Soren Hansen | bc1d3a0 | 2011-09-08 13:33:17 +0200 | [diff] [blame] | 335 | |
| 336 | # Create snapshot |
Brian Waldon | 883cb26 | 2011-11-02 11:30:07 -0400 | [diff] [blame] | 337 | image_data = {'name': 'testserver_snapshot'} |
Soren Hansen | bc1d3a0 | 2011-09-08 13:33:17 +0200 | [diff] [blame] | 338 | req_body = json.dumps({'createImage': image_data}) |
| 339 | url = '/servers/%s/action' % self.server_id |
| 340 | response, body = self.os.nova.request('POST', url, body=req_body) |
Soren Hansen | bc1d3a0 | 2011-09-08 13:33:17 +0200 | [diff] [blame] | 341 | self.assertEqual(response['status'], '202') |
| 342 | image_ref = response['location'] |
Soren Hansen | 5f4ad83 | 2011-09-09 14:08:19 +0200 | [diff] [blame] | 343 | snapshot_id = image_ref.rsplit('/', 1)[1] |
Soren Hansen | bc1d3a0 | 2011-09-08 13:33:17 +0200 | [diff] [blame] | 344 | |
| 345 | # Get snapshot and check its attributes |
| 346 | resp, body = self.os.nova.request('GET', '/images/%s' % snapshot_id) |
| 347 | snapshot = json.loads(body)['image'] |
| 348 | self.assertEqual(snapshot['name'], image_data['name']) |
| 349 | server_ref = snapshot['server']['links'][0]['href'] |
| 350 | self.assertTrue(server_ref.endswith('/%s' % self.server_id)) |
| 351 | |
Brian Waldon | 883cb26 | 2011-11-02 11:30:07 -0400 | [diff] [blame] | 352 | # Wait for first snapshot to start saving before making second snapshot |
| 353 | self.os.nova.wait_for_image_status(snapshot['id'], 'SAVING') |
| 354 | |
| 355 | # Create second snapshot |
| 356 | image_data = {'name': 'testserver_snapshot2'} |
| 357 | req_body = json.dumps({'createImage': image_data}) |
| 358 | url = '/servers/%s/action' % self.server_id |
| 359 | response, body = self.os.nova.request('POST', url, body=req_body) |
| 360 | self.assertEqual(response['status'], '409') |
| 361 | |
| 362 | # Ensure both snapshots succeed |
Soren Hansen | bc1d3a0 | 2011-09-08 13:33:17 +0200 | [diff] [blame] | 363 | self.os.nova.wait_for_image_status(snapshot['id'], 'ACTIVE') |
| 364 | |
| 365 | # Cleaning up |
| 366 | self.os.nova.request('DELETE', '/images/%s' % snapshot_id) |
Brian Waldon | 883cb26 | 2011-11-02 11:30:07 -0400 | [diff] [blame] | 367 | test_snapshot.tags = ['nova'] |
Soren Hansen | bc1d3a0 | 2011-09-08 13:33:17 +0200 | [diff] [blame] | 368 | |
Brian Waldon | 883cb26 | 2011-11-02 11:30:07 -0400 | [diff] [blame] | 369 | def test_snapshot_while_building(self): |
Soren Hansen | bc1d3a0 | 2011-09-08 13:33:17 +0200 | [diff] [blame] | 370 | """Ensure inability to snapshot server in BUILD state""" |
| 371 | |
Brian Waldon | 883cb26 | 2011-11-02 11:30:07 -0400 | [diff] [blame] | 372 | # Ensure server is in BUILD state |
| 373 | url = '/servers/%s' % self.server_id |
| 374 | response, body = self.os.nova.request('GET', url) |
| 375 | server = json.loads(body)['server'] |
| 376 | self.assertEqual(server['status'], 'BUILD', 'Server built too quickly') |
| 377 | |
Soren Hansen | bc1d3a0 | 2011-09-08 13:33:17 +0200 | [diff] [blame] | 378 | # Create snapshot |
Brian Waldon | 883cb26 | 2011-11-02 11:30:07 -0400 | [diff] [blame] | 379 | req_body = json.dumps({'createImage': {'name': 'testserver_snapshot'}}) |
Soren Hansen | bc1d3a0 | 2011-09-08 13:33:17 +0200 | [diff] [blame] | 380 | url = '/servers/%s/action' % self.server_id |
| 381 | response, body = self.os.nova.request('POST', url, body=req_body) |
| 382 | |
Brian Waldon | 883cb26 | 2011-11-02 11:30:07 -0400 | [diff] [blame] | 383 | # KNOWN-ISSUE 885232 |
| 384 | self.assertEqual(response['status'], '409') |
| 385 | test_snapshot_while_building.tags = ['nova'] |