blob: 255beb7210173d7ba5b3ed818ac4871361bba83e [file] [log] [blame]
Jay Pipes13b479b2012-06-11 14:52:27 -04001# vim: tabstop=4 shiftwidth=4 softtabstop=4
2
ZhiQiang Fan39f97222013-09-20 04:49:44 +08003# Copyright 2012 OpenStack Foundation
Jay Pipes13b479b2012-06-11 14:52:27 -04004# All Rights Reserved.
5#
6# Licensed under the Apache License, Version 2.0 (the "License"); you may
7# not use this file except in compliance with the License. You may obtain
8# a copy of the License at
9#
10# http://www.apache.org/licenses/LICENSE-2.0
11#
12# Unless required by applicable law or agreed to in writing, software
13# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
14# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
15# License for the specific language governing permissions and limitations
16# under the License.
17
Daryl Wallecked8bef32011-12-05 23:02:08 -060018import base64
Daryl Walleckb43ce8a2012-02-26 19:14:25 -060019import time
Brian Waldon738cd632011-12-12 18:45:09 -050020
ivan-zhu1feeb382013-01-24 10:14:39 +080021import testtools
Jay Pipes13b479b2012-06-11 14:52:27 -040022
Sean Dague1937d092013-05-17 16:36:38 -040023from tempest.api import compute
24from tempest.api.compute import base
Jay Pipes13b479b2012-06-11 14:52:27 -040025from tempest.common.utils.data_utils import rand_name
Daryl Walleck98e66dd2012-06-21 04:58:39 -050026from tempest.common.utils.linux.remote_client import RemoteClient
Matthew Treinisha83a16e2012-12-07 13:44:02 -050027import tempest.config
28from tempest import exceptions
Chris Yeoh9465b0b2013-02-09 22:19:15 +103029from tempest.test import attr
Giulio Fidente83181a92013-10-01 06:02:24 +020030from tempest.test import skip_because
Daryl Wallecked8bef32011-12-05 23:02:08 -060031
Daryl Walleckc7251962012-03-12 17:26:54 -050032
Attila Fazekas19044d52013-02-16 07:35:06 +010033class ServerActionsTestJSON(base.BaseComputeTest):
34 _interface = 'json'
Daryl Walleck587385b2012-03-03 13:00:26 -060035 resize_available = tempest.config.TempestConfig().compute.resize_available
Daryl Walleck98e66dd2012-06-21 04:58:39 -050036 run_ssh = tempest.config.TempestConfig().compute.run_ssh
Daryl Wallecked8bef32011-12-05 23:02:08 -060037
Attila Fazekas19044d52013-02-16 07:35:06 +010038 def setUp(self):
Attila Fazekasf7f34f92013-08-01 17:01:44 +020039 # NOTE(afazekas): Normally we use the same server with all test cases,
Attila Fazekas45c3fbc2013-02-24 16:39:52 +010040 # but if it has an issue, we build a new one
Attila Fazekas19044d52013-02-16 07:35:06 +010041 super(ServerActionsTestJSON, self).setUp()
42 # Check if the server is in a clean state after test
43 try:
44 self.client.wait_for_server_status(self.server_id, 'ACTIVE')
afazekas14025cd2013-03-13 23:42:17 +010045 except Exception:
Attila Fazekas19044d52013-02-16 07:35:06 +010046 # Rebuild server if something happened to it during a test
Ken'ichi Ohmichida306502013-10-08 23:44:55 +090047 self.rebuild_server()
Attila Fazekas19044d52013-02-16 07:35:06 +010048
49 @classmethod
50 def setUpClass(cls):
51 super(ServerActionsTestJSON, cls).setUpClass()
52 cls.client = cls.servers_client
Ken'ichi Ohmichida306502013-10-08 23:44:55 +090053 cls.rebuild_server()
Attila Fazekas19044d52013-02-16 07:35:06 +010054
ivan-zhu1feeb382013-01-24 10:14:39 +080055 @testtools.skipUnless(compute.CHANGE_PASSWORD_AVAILABLE,
56 'Change password not available.')
Giampaolo Lauriae9c77022013-05-22 01:23:58 -040057 @attr(type='gate')
Daryl Wallecked8bef32011-12-05 23:02:08 -060058 def test_change_server_password(self):
Sean Dague4dd2c0b2013-01-03 17:50:28 -050059 # The server's password should be set to the provided password
Daryl Walleck98e66dd2012-06-21 04:58:39 -050060 new_password = 'Newpass1234'
61 resp, body = self.client.change_password(self.server_id, new_password)
Daryl Wallecked8bef32011-12-05 23:02:08 -060062 self.assertEqual(202, resp.status)
Brian Waldon3bde07f2011-12-13 15:11:22 -050063 self.client.wait_for_server_status(self.server_id, 'ACTIVE')
Daryl Wallecked8bef32011-12-05 23:02:08 -060064
Daryl Walleck98e66dd2012-06-21 04:58:39 -050065 if self.run_ssh:
66 # Verify that the user can authenticate with the new password
67 resp, server = self.client.get_server(self.server_id)
68 linux_client = RemoteClient(server, self.ssh_user, new_password)
69 self.assertTrue(linux_client.can_authenticate())
70
Daryl Wallecked8bef32011-12-05 23:02:08 -060071 @attr(type='smoke')
72 def test_reboot_server_hard(self):
Sean Dague4dd2c0b2013-01-03 17:50:28 -050073 # The server should be power cycled
Daryl Walleck98e66dd2012-06-21 04:58:39 -050074 if self.run_ssh:
75 # Get the time the server was last rebooted,
Daryl Walleck98e66dd2012-06-21 04:58:39 -050076 resp, server = self.client.get_server(self.server_id)
77 linux_client = RemoteClient(server, self.ssh_user, self.password)
78 boot_time = linux_client.get_boot_time()
Daryl Walleck98e66dd2012-06-21 04:58:39 -050079
Brian Waldon3bde07f2011-12-13 15:11:22 -050080 resp, body = self.client.reboot(self.server_id, 'HARD')
Daryl Wallecked8bef32011-12-05 23:02:08 -060081 self.assertEqual(202, resp.status)
Brian Waldon3bde07f2011-12-13 15:11:22 -050082 self.client.wait_for_server_status(self.server_id, 'ACTIVE')
Daryl Wallecked8bef32011-12-05 23:02:08 -060083
Daryl Walleck98e66dd2012-06-21 04:58:39 -050084 if self.run_ssh:
85 # Log in and verify the boot time has changed
86 linux_client = RemoteClient(server, self.ssh_user, self.password)
87 new_boot_time = linux_client.get_boot_time()
88 self.assertGreater(new_boot_time, boot_time)
89
Giulio Fidente83181a92013-10-01 06:02:24 +020090 @skip_because(bug="1014647")
Giampaolo Lauriae9c77022013-05-22 01:23:58 -040091 @attr(type='smoke')
Daryl Wallecked8bef32011-12-05 23:02:08 -060092 def test_reboot_server_soft(self):
Sean Dague4dd2c0b2013-01-03 17:50:28 -050093 # The server should be signaled to reboot gracefully
Daryl Walleck98e66dd2012-06-21 04:58:39 -050094 if self.run_ssh:
95 # Get the time the server was last rebooted,
Daryl Walleck98e66dd2012-06-21 04:58:39 -050096 resp, server = self.client.get_server(self.server_id)
97 linux_client = RemoteClient(server, self.ssh_user, self.password)
98 boot_time = linux_client.get_boot_time()
Daryl Walleck98e66dd2012-06-21 04:58:39 -050099
Brian Waldon3bde07f2011-12-13 15:11:22 -0500100 resp, body = self.client.reboot(self.server_id, 'SOFT')
Daryl Wallecked8bef32011-12-05 23:02:08 -0600101 self.assertEqual(202, resp.status)
Brian Waldon3bde07f2011-12-13 15:11:22 -0500102 self.client.wait_for_server_status(self.server_id, 'ACTIVE')
Daryl Wallecked8bef32011-12-05 23:02:08 -0600103
Daryl Walleck98e66dd2012-06-21 04:58:39 -0500104 if self.run_ssh:
105 # Log in and verify the boot time has changed
106 linux_client = RemoteClient(server, self.ssh_user, self.password)
107 new_boot_time = linux_client.get_boot_time()
108 self.assertGreater(new_boot_time, boot_time)
109
Daryl Wallecked8bef32011-12-05 23:02:08 -0600110 @attr(type='smoke')
111 def test_rebuild_server(self):
Sean Dague4dd2c0b2013-01-03 17:50:28 -0500112 # The server should be rebuilt using the provided image and data
Daryl Wallecked8bef32011-12-05 23:02:08 -0600113 meta = {'rebuild': 'server'}
Brian Waldon738cd632011-12-12 18:45:09 -0500114 new_name = rand_name('server')
Daryl Wallecked8bef32011-12-05 23:02:08 -0600115 file_contents = 'Test server rebuild.'
Mahesh Panchaksharaiah21599a92013-07-03 15:28:58 +0530116 personality = [{'path': 'rebuild.txt',
Daryl Wallecked8bef32011-12-05 23:02:08 -0600117 'contents': base64.b64encode(file_contents)}]
Daryl Walleck98e66dd2012-06-21 04:58:39 -0500118 password = 'rebuildPassw0rd'
Brian Waldon3bde07f2011-12-13 15:11:22 -0500119 resp, rebuilt_server = self.client.rebuild(self.server_id,
Daryl Wallecked8bef32011-12-05 23:02:08 -0600120 self.image_ref_alt,
ivan-zhu454b1c52013-09-30 16:40:21 +0800121 name=new_name,
122 metadata=meta,
Daryl Wallecked8bef32011-12-05 23:02:08 -0600123 personality=personality,
Daryl Walleck98e66dd2012-06-21 04:58:39 -0500124 adminPass=password)
Daryl Wallecked8bef32011-12-05 23:02:08 -0600125
Attila Fazekasf7f34f92013-08-01 17:01:44 +0200126 # Verify the properties in the initial response are correct
Brian Waldon3bde07f2011-12-13 15:11:22 -0500127 self.assertEqual(self.server_id, rebuilt_server['id'])
Eoghan Glynn57c1a3d2012-03-01 16:50:29 -0500128 rebuilt_image_id = rebuilt_server['image']['id']
129 self.assertTrue(self.image_ref_alt.endswith(rebuilt_image_id))
Matthew Treinish39e48ef2012-12-21 13:36:15 -0500130 self.assertEqual(self.flavor_ref, int(rebuilt_server['flavor']['id']))
Daryl Wallecked8bef32011-12-05 23:02:08 -0600131
Attila Fazekasf7f34f92013-08-01 17:01:44 +0200132 # Verify the server properties after the rebuild completes
Daryl Wallecked8bef32011-12-05 23:02:08 -0600133 self.client.wait_for_server_status(rebuilt_server['id'], 'ACTIVE')
134 resp, server = self.client.get_server(rebuilt_server['id'])
Eoghan Glynn57c1a3d2012-03-01 16:50:29 -0500135 rebuilt_image_id = rebuilt_server['image']['id']
136 self.assertTrue(self.image_ref_alt.endswith(rebuilt_image_id))
Brian Waldon738cd632011-12-12 18:45:09 -0500137 self.assertEqual(new_name, rebuilt_server['name'])
Daryl Wallecked8bef32011-12-05 23:02:08 -0600138
Daryl Walleck98e66dd2012-06-21 04:58:39 -0500139 if self.run_ssh:
140 # Verify that the user can authenticate with the provided password
141 linux_client = RemoteClient(server, self.ssh_user, password)
142 self.assertTrue(linux_client.can_authenticate())
143
Tiago Mello52d8fda2013-02-12 12:10:30 -0500144 def _detect_server_image_flavor(self, server_id):
145 # Detects the current server image flavor ref.
146 resp, server = self.client.get_server(self.server_id)
147 current_flavor = server['flavor']['id']
148 new_flavor_ref = self.flavor_ref_alt \
149 if int(current_flavor) == self.flavor_ref else self.flavor_ref
150 return int(current_flavor), int(new_flavor_ref)
151
ivan-zhu1feeb382013-01-24 10:14:39 +0800152 @testtools.skipIf(not resize_available, 'Resize not available.')
Giampaolo Lauriae9c77022013-05-22 01:23:58 -0400153 @attr(type='smoke')
Daryl Wallecked8bef32011-12-05 23:02:08 -0600154 def test_resize_server_confirm(self):
Sean Dague4dd2c0b2013-01-03 17:50:28 -0500155 # The server's RAM and disk space should be modified to that of
156 # the provided flavor
Daryl Wallecked8bef32011-12-05 23:02:08 -0600157
Tiago Mello52d8fda2013-02-12 12:10:30 -0500158 previous_flavor_ref, new_flavor_ref = \
159 self._detect_server_image_flavor(self.server_id)
160
161 resp, server = self.client.resize(self.server_id, new_flavor_ref)
Daryl Wallecked8bef32011-12-05 23:02:08 -0600162 self.assertEqual(202, resp.status)
Brian Waldon3bde07f2011-12-13 15:11:22 -0500163 self.client.wait_for_server_status(self.server_id, 'VERIFY_RESIZE')
Daryl Wallecked8bef32011-12-05 23:02:08 -0600164
Brian Waldon3bde07f2011-12-13 15:11:22 -0500165 self.client.confirm_resize(self.server_id)
166 self.client.wait_for_server_status(self.server_id, 'ACTIVE')
Daryl Wallecked8bef32011-12-05 23:02:08 -0600167
Brian Waldon3bde07f2011-12-13 15:11:22 -0500168 resp, server = self.client.get_server(self.server_id)
Tiago Mello52d8fda2013-02-12 12:10:30 -0500169 self.assertEqual(new_flavor_ref, int(server['flavor']['id']))
Daryl Wallecked8bef32011-12-05 23:02:08 -0600170
ivan-zhu1feeb382013-01-24 10:14:39 +0800171 @testtools.skipIf(not resize_available, 'Resize not available.')
Giulio Fidenteba3985a2013-05-29 01:46:36 +0200172 @attr(type='gate')
Daryl Wallecked8bef32011-12-05 23:02:08 -0600173 def test_resize_server_revert(self):
Sean Dague4dd2c0b2013-01-03 17:50:28 -0500174 # The server's RAM and disk space should return to its original
175 # values after a resize is reverted
Daryl Wallecked8bef32011-12-05 23:02:08 -0600176
Tiago Mello52d8fda2013-02-12 12:10:30 -0500177 previous_flavor_ref, new_flavor_ref = \
178 self._detect_server_image_flavor(self.server_id)
179
180 resp, server = self.client.resize(self.server_id, new_flavor_ref)
Daryl Wallecked8bef32011-12-05 23:02:08 -0600181 self.assertEqual(202, resp.status)
Brian Waldon3bde07f2011-12-13 15:11:22 -0500182 self.client.wait_for_server_status(self.server_id, 'VERIFY_RESIZE')
Daryl Wallecked8bef32011-12-05 23:02:08 -0600183
Brian Waldon3bde07f2011-12-13 15:11:22 -0500184 self.client.revert_resize(self.server_id)
185 self.client.wait_for_server_status(self.server_id, 'ACTIVE')
Daryl Wallecked8bef32011-12-05 23:02:08 -0600186
Daryl Walleckb43ce8a2012-02-26 19:14:25 -0600187 # Need to poll for the id change until lp#924371 is fixed
Brian Waldon3bde07f2011-12-13 15:11:22 -0500188 resp, server = self.client.get_server(self.server_id)
Daryl Walleckb43ce8a2012-02-26 19:14:25 -0600189 start = int(time.time())
190
Tiago Mello52d8fda2013-02-12 12:10:30 -0500191 while int(server['flavor']['id']) != previous_flavor_ref:
Daryl Walleckb43ce8a2012-02-26 19:14:25 -0600192 time.sleep(self.build_interval)
193 resp, server = self.client.get_server(self.server_id)
194
195 if int(time.time()) - start >= self.build_timeout:
196 message = 'Server %s failed to revert resize within the \
197 required time (%s s).' % (self.server_id, self.build_timeout)
198 raise exceptions.TimeoutException(message)
sapan-konaf1e3f002011-12-22 23:18:44 +0530199
Giampaolo Lauriae9c77022013-05-22 01:23:58 -0400200 @attr(type=['negative', 'gate'])
Zhi Kun Liu3c44af32013-09-02 23:34:57 +0800201 def test_resize_server_using_nonexist_flavor(self):
202 flavor_id = -1
203 self.assertRaises(exceptions.BadRequest,
204 self.client.resize, self.server_id, flavor_id)
205
206 @attr(type=['negative', 'gate'])
207 def test_resize_server_using_null_flavor(self):
208 flavor_id = ""
209 self.assertRaises(exceptions.BadRequest,
210 self.client.resize, self.server_id, flavor_id)
211
212 @attr(type=['negative', 'gate'])
Joe Gordonddf39272012-09-13 15:04:55 -0700213 def test_reboot_nonexistent_server_soft(self):
Sean Dague4dd2c0b2013-01-03 17:50:28 -0500214 # Negative Test: The server reboot on non existent server should return
215 # an error
David Kranz5a23d862012-02-14 09:48:55 -0500216 self.assertRaises(exceptions.NotFound, self.client.reboot, 999, 'SOFT')
sapan-konaf1e3f002011-12-22 23:18:44 +0530217
Giampaolo Lauriae9c77022013-05-22 01:23:58 -0400218 @attr(type=['negative', 'gate'])
Joe Gordonddf39272012-09-13 15:04:55 -0700219 def test_rebuild_nonexistent_server(self):
Sean Dague4dd2c0b2013-01-03 17:50:28 -0500220 # Negative test: The server rebuild for a non existing server
221 # should not be allowed
sapan-konaf1e3f002011-12-22 23:18:44 +0530222 meta = {'rebuild': 'server'}
223 new_name = rand_name('server')
224 file_contents = 'Test server rebuild.'
225 personality = [{'path': '/etc/rebuild.txt',
226 'contents': base64.b64encode(file_contents)}]
Attila Fazekas45c3fbc2013-02-24 16:39:52 +0100227 self.assertRaises(exceptions.NotFound,
228 self.client.rebuild,
229 999, self.image_ref_alt,
ivan-zhu454b1c52013-09-30 16:40:21 +0800230 name=new_name,
231 metadata=meta,
Attila Fazekas45c3fbc2013-02-24 16:39:52 +0100232 personality=personality,
233 adminPass='rebuild')
234
Giulio Fidenteba3985a2013-05-29 01:46:36 +0200235 @attr(type='gate')
Attila Fazekas45c3fbc2013-02-24 16:39:52 +0100236 def test_get_console_output(self):
237 # Positive test:Should be able to GET the console output
238 # for a given server_id and number of lines
239 def get_output():
240 resp, output = self.servers_client.get_console_output(
241 self.server_id, 10)
242 self.assertEqual(200, resp.status)
Ionuț Arțărișia767b522013-08-21 18:09:26 +0200243 self.assertTrue(output, "Console output was empty.")
Attila Fazekas45c3fbc2013-02-24 16:39:52 +0100244 lines = len(output.split('\n'))
245 self.assertEqual(lines, 10)
246 self.wait_for(get_output)
247
Giampaolo Lauriae9c77022013-05-22 01:23:58 -0400248 @attr(type=['negative', 'gate'])
Attila Fazekas45c3fbc2013-02-24 16:39:52 +0100249 def test_get_console_output_invalid_server_id(self):
250 # Negative test: Should not be able to get the console output
251 # for an invalid server_id
252 self.assertRaises(exceptions.NotFound,
253 self.servers_client.get_console_output,
254 '!@#$%^&*()', 10)
255
Giulio Fidente83181a92013-10-01 06:02:24 +0200256 @skip_because(bug="1014683")
Giulio Fidenteba3985a2013-05-29 01:46:36 +0200257 @attr(type='gate')
Attila Fazekas45c3fbc2013-02-24 16:39:52 +0100258 def test_get_console_output_server_id_in_reboot_status(self):
259 # Positive test:Should be able to GET the console output
260 # for a given server_id in reboot status
261 resp, output = self.servers_client.reboot(self.server_id, 'SOFT')
262 self.servers_client.wait_for_server_status(self.server_id,
263 'REBOOT')
264 resp, output = self.servers_client.get_console_output(self.server_id,
265 10)
266 self.assertEqual(200, resp.status)
Ionuț Arțăriși7f7d4522013-08-21 11:47:47 +0200267 self.assertIsNotNone(output)
Attila Fazekas45c3fbc2013-02-24 16:39:52 +0100268 lines = len(output.split('\n'))
269 self.assertEqual(lines, 10)
Dan Smithbc3bd242012-08-14 09:48:48 -0700270
Prem Karat6631f802013-07-04 12:07:33 +0530271 @attr(type='gate')
272 def test_pause_unpause_server(self):
273 resp, server = self.client.pause_server(self.server_id)
274 self.assertEqual(202, resp.status)
275 self.client.wait_for_server_status(self.server_id, 'PAUSED')
276 resp, server = self.client.unpause_server(self.server_id)
277 self.assertEqual(202, resp.status)
278 self.client.wait_for_server_status(self.server_id, 'ACTIVE')
279
280 @attr(type='gate')
281 def test_suspend_resume_server(self):
282 resp, server = self.client.suspend_server(self.server_id)
283 self.assertEqual(202, resp.status)
284 self.client.wait_for_server_status(self.server_id, 'SUSPENDED')
285 resp, server = self.client.resume_server(self.server_id)
286 self.assertEqual(202, resp.status)
287 self.client.wait_for_server_status(self.server_id, 'ACTIVE')
288
Anju Tiwariaf98d222013-08-05 15:19:50 +0530289 @attr(type='gate')
290 def test_stop_start_server(self):
291 resp, server = self.servers_client.stop(self.server_id)
292 self.assertEqual(202, resp.status)
293 self.servers_client.wait_for_server_status(self.server_id, 'SHUTOFF')
294 resp, server = self.servers_client.start(self.server_id)
295 self.assertEqual(202, resp.status)
296 self.servers_client.wait_for_server_status(self.server_id, 'ACTIVE')
297
ivan-zhu44e08652013-10-08 16:42:46 +0800298 @skip_because(bug="1233026")
Zhu Zhu9643e512013-09-23 09:13:07 -0500299 @attr(type='gate')
300 def test_lock_unlock_server(self):
301 # Lock the server,try server stop(exceptions throw),unlock it and retry
302 resp, server = self.servers_client.lock_server(self.server_id)
303 self.assertEqual(202, resp.status)
304 resp, server = self.servers_client.get_server(self.server_id)
305 self.assertEqual(200, resp.status)
306 self.assertEqual(server['status'], 'ACTIVE')
307 # Locked server is not allowed to be stopped by non-admin user
308 self.assertRaises(exceptions.BadRequest,
309 self.servers_client.stop, self.server_id)
310 resp, server = self.servers_client.unlock_server(self.server_id)
311 self.assertEqual(202, resp.status)
312 resp, server = self.servers_client.stop(self.server_id)
313 self.assertEqual(202, resp.status)
314 self.servers_client.wait_for_server_status(self.server_id, 'SHUTOFF')
315 resp, server = self.servers_client.start(self.server_id)
316 self.assertEqual(202, resp.status)
317 self.servers_client.wait_for_server_status(self.server_id, 'ACTIVE')
318
Dan Smithbc3bd242012-08-14 09:48:48 -0700319
Attila Fazekas19044d52013-02-16 07:35:06 +0100320class ServerActionsTestXML(ServerActionsTestJSON):
321 _interface = 'xml'